Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.depend b/.depend
index 2b29e3879da1..c6725ec77125 100644
--- a/.depend
+++ b/.depend
@@ -1,175 +1,171 @@
# DO NOT DELETE
addrmatch.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 match.h log.h
atomicio.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 atomicio.h
audit-bsm.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
audit-linux.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
audit.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
auth-bsdauth.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
-auth-krb5.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 ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h sshbuf.h sshkey.h misc.h servconf.h uidswap.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+auth-krb5.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 ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h sshbuf.h sshkey.h misc.h servconf.h uidswap.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
auth-options.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 ssherr.h log.h sshbuf.h misc.h sshkey.h match.h ssh2.h auth-options.h
auth-pam.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
-auth-passwd.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h sshbuf.h ssherr.h log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h
-auth-rhosts.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h uidswap.h pathnames.h log.h misc.h sshbuf.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+auth-passwd.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 packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h ssherr.h log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h
+auth-rhosts.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 packet.h openbsd-compat/sys-queue.h dispatch.h uidswap.h pathnames.h log.h misc.h sshbuf.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
auth-shadow.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
auth-sia.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
auth-skey.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
-auth.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 groupaccess.h log.h sshbuf.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h
-auth.o: authfile.h monitor_wrap.h ssherr.h compat.h channels.h
-auth2-chall.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 ssh2.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssherr.h log.h misc.h servconf.h
+auth.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 groupaccess.h log.h sshbuf.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h openbsd-compat/sys-queue.h dispatch.h authfile.h
+auth.o: monitor_wrap.h ssherr.h compat.h channels.h
+auth2-chall.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 ssh2.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h misc.h servconf.h
auth2-gss.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
-auth2-hostbased.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 ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h sshbuf.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h monitor_wrap.h
-auth2-hostbased.o: pathnames.h ssherr.h match.h
-auth2-kbdint.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h hostfile.h auth.h auth-pam.h audit.h loginrec.h log.h misc.h servconf.h ssherr.h
-auth2-none.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 atomicio.h xmalloc.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h misc.h servconf.h compat.h ssh2.h ssherr.h monitor_wrap.h
-auth2-passwd.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssherr.h log.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h monitor_wrap.h misc.h servconf.h
-auth2-pubkey.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 ssh.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h sshbuf.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h uidswap.h
-auth2-pubkey.o: auth-options.h canohost.h monitor_wrap.h authfile.h match.h ssherr.h channels.h session.h
-auth2.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 atomicio.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h sshbuf.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h ssherr.h
-auth2.o: monitor_wrap.h digest.h
+auth2-hostbased.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 ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h monitor_wrap.h pathnames.h
+auth2-hostbased.o: ssherr.h match.h
+auth2-kbdint.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 packet.h openbsd-compat/sys-queue.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h log.h misc.h servconf.h ssherr.h
+auth2-none.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 atomicio.h xmalloc.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h misc.h servconf.h compat.h ssh2.h ssherr.h monitor_wrap.h
+auth2-passwd.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 packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h monitor_wrap.h misc.h servconf.h
+auth2-pubkey.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 ssh.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h uidswap.h auth-options.h
+auth2-pubkey.o: canohost.h monitor_wrap.h authfile.h match.h ssherr.h channels.h session.h
+auth2.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 atomicio.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h sshbuf.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h ssherr.h monitor_wrap.h
+auth2.o: digest.h
authfd.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 ssh.h sshbuf.h sshkey.h authfd.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h compat.h log.h atomicio.h misc.h ssherr.h
authfile.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 cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h ssh.h log.h authfile.h misc.h atomicio.h sshkey.h sshbuf.h ssherr.h krl.h
bitmap.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 bitmap.h
-canohost.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h canohost.h misc.h
+canohost.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 packet.h openbsd-compat/sys-queue.h dispatch.h log.h canohost.h misc.h
chacha.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 chacha.h
-channels.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 ssherr.h sshbuf.h packet.h dispatch.h opacket.h log.h misc.h channels.h compat.h canohost.h sshkey.h authfd.h pathnames.h match.h
+channels.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 ssherr.h sshbuf.h packet.h dispatch.h log.h misc.h channels.h compat.h canohost.h sshkey.h authfd.h pathnames.h match.h
cipher-aes.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/openssl-compat.h
cipher-aesctr.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 cipher-aesctr.h rijndael.h
cipher-chachapoly.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 log.h sshbuf.h ssherr.h cipher-chachapoly.h chacha.h poly1305.h
cipher-ctr.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
cipher.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 cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h misc.h sshbuf.h ssherr.h digest.h openbsd-compat/openssl-compat.h
cleanup.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 log.h
-clientloop.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 packet.h dispatch.h opacket.h sshbuf.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h
+clientloop.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 packet.h dispatch.h sshbuf.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h
clientloop.o: myproposal.h log.h misc.h readconf.h clientloop.h sshconnect.h authfd.h atomicio.h sshpty.h match.h msg.h ssherr.h hostfile.h
-compat.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h log.h match.h kex.h mac.h
+compat.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 packet.h openbsd-compat/sys-queue.h dispatch.h compat.h log.h match.h kex.h mac.h crypto_api.h
crc32.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 crc32.h
dh.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
digest-libc.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 digest.h
digest-openssl.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
-dispatch.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 log.h dispatch.h packet.h openbsd-compat/sys-queue.h opacket.h compat.h ssherr.h
+dispatch.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 log.h dispatch.h packet.h openbsd-compat/sys-queue.h compat.h ssherr.h
dns.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 sshkey.h ssherr.h dns.h log.h digest.h
ed25519.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 crypto_api.h ge25519.h fe25519.h sc25519.h
entropy.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
fatal.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 log.h
fe25519.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 fe25519.h crypto_api.h
ge25519.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 fe25519.h crypto_api.h sc25519.h ge25519.h ge25519_base.data
groupaccess.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 groupaccess.h match.h log.h
gss-genr.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
gss-serv-krb5.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
gss-serv.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
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
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: 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
-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
+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 compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h log.h match.h
+kex.o: misc.h 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 sshkey.h kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h ssh2.h
kexdh.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
-kexdhc.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
-kexdhs.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
kexecdh.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
-kexecdhc.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
-kexecdhs.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
+kexgen.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 kex.h mac.h crypto_api.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h ssh2.h sshbuf.h digest.h ssherr.h
kexgex.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
kexgexc.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
kexgexs.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
+kexsntrup4591761x25519.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 kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h
krl.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 sshbuf.h ssherr.h sshkey.h authfile.h misc.h log.h digest.h bitmap.h krl.h
log.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 log.h
-loginrec.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 sshkey.h hostfile.h ssh.h loginrec.h log.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h canohost.h auth.h auth-pam.h audit.h sshbuf.h ssherr.h
+loginrec.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 sshkey.h hostfile.h ssh.h loginrec.h log.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h canohost.h auth.h auth-pam.h audit.h sshbuf.h ssherr.h
logintest.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 loginrec.h
mac.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 digest.h hmac.h umac.h mac.h misc.h ssherr.h sshbuf.h openbsd-compat/openssl-compat.h
match.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 misc.h
md5crypt.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
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 xmalloc.h misc.h log.h ssh.h sshbuf.h ssherr.h
moduli.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
monitor.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 openbsd-compat/openssl-compat.h atomicio.h xmalloc.h ssh.h sshkey.h sshbuf.h hostfile.h auth.h auth-pam.h audit.h loginrec.h cipher.h cipher-chachapoly.h
-monitor.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h dh.h packet.h dispatch.h opacket.h auth-options.h sshpty.h channels.h session.h sshlogin.h canohost.h log.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h ssherr.h
+monitor.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h dh.h packet.h dispatch.h auth-options.h sshpty.h channels.h session.h sshlogin.h canohost.h log.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h ssherr.h
monitor_fdpass.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 log.h monitor_fdpass.h
-monitor_wrap.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 sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
-monitor_wrap.o: auth-options.h packet.h dispatch.h opacket.h log.h monitor.h monitor_wrap.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.h ssherr.h
+monitor_wrap.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 sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+monitor_wrap.o: auth-options.h packet.h dispatch.h log.h monitor.h monitor_wrap.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.h ssherr.h
msg.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 ssherr.h log.h atomicio.h msg.h misc.h
-mux.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 log.h ssh.h ssh2.h pathnames.h misc.h match.h sshbuf.h channels.h msg.h packet.h dispatch.h opacket.h monitor_fdpass.h sshpty.h sshkey.h readconf.h clientloop.h ssherr.h
-nchan.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 ssh2.h sshbuf.h ssherr.h packet.h dispatch.h opacket.h channels.h compat.h log.h
-opacket.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h
-packet.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 crc32.h compat.h ssh2.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h digest.h log.h canohost.h misc.h channels.h ssh.h
-packet.o: packet.h dispatch.h opacket.h ssherr.h sshbuf.h
+mux.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 log.h ssh.h ssh2.h pathnames.h misc.h match.h sshbuf.h channels.h msg.h packet.h dispatch.h monitor_fdpass.h sshpty.h sshkey.h readconf.h clientloop.h ssherr.h
+nchan.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 ssh2.h sshbuf.h ssherr.h packet.h dispatch.h channels.h compat.h log.h
+packet.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 crc32.h compat.h ssh2.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h digest.h log.h canohost.h misc.h channels.h
+packet.o: ssh.h packet.h dispatch.h ssherr.h sshbuf.h
platform-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
platform-pledge.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
platform-tracing.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 log.h
platform.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 log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
poly1305.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 poly1305.h
-progressmeter.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 progressmeter.h atomicio.h misc.h
-readconf.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/glob.h xmalloc.h ssh.h ssherr.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h pathnames.h log.h sshkey.h misc.h readconf.h match.h kex.h mac.h uidswap.h
-readconf.o: myproposal.h digest.h
+progressmeter.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 progressmeter.h atomicio.h misc.h utf8.h
+readconf.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/glob.h xmalloc.h ssh.h ssherr.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h pathnames.h log.h sshkey.h misc.h readconf.h match.h kex.h mac.h crypto_api.h
+readconf.o: uidswap.h myproposal.h digest.h
readpass.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 misc.h pathnames.h log.h ssh.h uidswap.h
rijndael.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 rijndael.h
sandbox-capsicum.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
sandbox-darwin.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
sandbox-null.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
sandbox-pledge.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
sandbox-rlimit.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
sandbox-seccomp-filter.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
sandbox-solaris.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
sandbox-systrace.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
sc25519.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 sc25519.h crypto_api.h
scp.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 ssh.h atomicio.h pathnames.h log.h misc.h progressmeter.h utf8.h
-servconf.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 log.h sshbuf.h misc.h servconf.h compat.h pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h match.h channels.h
-servconf.o: groupaccess.h canohost.h packet.h dispatch.h opacket.h ssherr.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h
-serverloop.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 packet.h dispatch.h opacket.h sshbuf.h log.h misc.h servconf.h canohost.h sshpty.h channels.h compat.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h
-serverloop.o: cipher-aesctr.h rijndael.h kex.h mac.h hostfile.h auth.h auth-pam.h audit.h loginrec.h session.h auth-options.h serverloop.h ssherr.h
-session.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 sshpty.h packet.h dispatch.h opacket.h sshbuf.h ssherr.h match.h uidswap.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h
-session.o: cipher-aesctr.h rijndael.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfd.h pathnames.h log.h misc.h servconf.h sshlogin.h serverloop.h canohost.h session.h kex.h mac.h monitor_wrap.h sftp.h atomicio.h
+servconf.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 log.h sshbuf.h misc.h servconf.h compat.h pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h
+servconf.o: match.h channels.h groupaccess.h canohost.h packet.h dispatch.h ssherr.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h
+serverloop.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 packet.h dispatch.h sshbuf.h log.h misc.h servconf.h canohost.h sshpty.h channels.h compat.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h
+serverloop.o: rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h session.h auth-options.h serverloop.h ssherr.h
+session.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 sshpty.h packet.h dispatch.h sshbuf.h ssherr.h match.h uidswap.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h
+session.o: rijndael.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfd.h pathnames.h log.h misc.h servconf.h sshlogin.h serverloop.h canohost.h session.h kex.h mac.h crypto_api.h monitor_wrap.h sftp.h atomicio.h
sftp-client.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 ssherr.h sshbuf.h log.h atomicio.h progressmeter.h misc.h utf8.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h
sftp-common.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 ssherr.h sshbuf.h log.h misc.h sftp.h sftp-common.h
sftp-glob.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 sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h
sftp-server-main.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 log.h sftp.h misc.h xmalloc.h
sftp-server.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 sshbuf.h ssherr.h log.h misc.h match.h uidswap.h sftp.h sftp-common.h
sftp.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 log.h pathnames.h misc.h utf8.h sftp.h ssherr.h sshbuf.h sftp-common.h sftp-client.h openbsd-compat/glob.h
+sntrup4591761.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 crypto_api.h
ssh-add.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/openssl-compat.h xmalloc.h ssh.h log.h sshkey.h sshbuf.h authfd.h authfile.h pathnames.h misc.h ssherr.h digest.h
ssh-agent.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 sshbuf.h sshkey.h authfd.h compat.h log.h misc.h digest.h ssherr.h match.h
ssh-dss.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-ecdsa.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-ed25519.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 crypto_api.h log.h sshbuf.h sshkey.h ssherr.h ssh.h
ssh-keygen.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 sshkey.h authfile.h uuencode.h sshbuf.h pathnames.h log.h misc.h match.h hostfile.h dns.h ssh.h ssh2.h ssherr.h ssh-pkcs11.h atomicio.h krl.h digest.h utf8.h authfd.h
-ssh-keyscan.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 sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h compat.h myproposal.h packet.h dispatch.h opacket.h log.h
+ssh-keyscan.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 sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h compat.h myproposal.h packet.h dispatch.h log.h
ssh-keyscan.o: atomicio.h misc.h hostfile.h ssherr.h ssh_api.h ssh2.h dns.h
ssh-keysign.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 log.h sshkey.h ssh.h ssh2.h misc.h sshbuf.h authfile.h msg.h canohost.h pathnames.h readconf.h uidswap.h ssherr.h
ssh-pkcs11-client.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-pkcs11-helper.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 sshbuf.h log.h misc.h sshkey.h authfd.h ssh-pkcs11.h ssherr.h
ssh-pkcs11.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-rsa.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-xmss.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.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/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h packet.h dispatch.h opacket.h
-ssh.o: sshbuf.h channels.h sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h misc.h readconf.h sshconnect.h kex.h mac.h sshpty.h match.h msg.h version.h ssherr.h myproposal.h utf8.h
-ssh_api.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_api.h openbsd-compat/sys-queue.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h ssh.h ssh2.h packet.h dispatch.h opacket.h compat.h log.h authfile.h misc.h
-ssh_api.o: version.h myproposal.h ssherr.h sshbuf.h
+ssh.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/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h packet.h dispatch.h sshbuf.h
+ssh.o: channels.h sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h ssherr.h myproposal.h utf8.h
+ssh_api.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_api.h openbsd-compat/sys-queue.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h ssh.h ssh2.h packet.h dispatch.h compat.h log.h authfile.h misc.h
+ssh_api.o: version.h myproposal.h ssherr.h sshbuf.h openbsd-compat/openssl-compat.h
sshbuf-getput-basic.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-getput-crypto.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
-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
-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
+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 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 ssherr.h
+sshconnect.o: authfd.h kex.h mac.h crypto_api.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 compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.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
-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: poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h myproposal.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h auth-options.h version.h ssherr.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 log.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h
+sshd.o: cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h crypto_api.h myproposal.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h auth-options.h version.h ssherr.h
ssherr.o: ssherr.h
sshkey-xmss.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.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 crypto_api.h ssh2.h ssherr.h misc.h sshbuf.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h sshkey-xmss.h match.h xmss_fast.h openbsd-compat/openssl-compat.h
sshlogin.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 sshlogin.h ssherr.h loginrec.h log.h sshbuf.h misc.h servconf.h
sshpty.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 sshpty.h log.h misc.h
sshtty.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 sshpty.h
-ttymodes.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 packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h log.h compat.h sshbuf.h ssherr.h ttymodes.h
+ttymodes.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 packet.h openbsd-compat/sys-queue.h dispatch.h log.h compat.h sshbuf.h ssherr.h ttymodes.h
uidswap.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 log.h uidswap.h xmalloc.h
umac.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 umac.h misc.h rijndael.h
umac128.o: umac.c 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 umac.h misc.h rijndael.h
utf8.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 utf8.h
uuencode.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 uuencode.h
verify.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 crypto_api.h
xmalloc.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 log.h
xmss_commons.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
xmss_fast.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
xmss_hash.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
xmss_hash_address.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
xmss_wots.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
diff --git a/.gitignore b/.gitignore
index 650eb3c3c90c..e7e02ea720df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,28 +1,29 @@
Makefile
buildpkg.sh
config.h
config.h.in
config.status
configure
openbsd-compat/Makefile
openbsd-compat/regress/Makefile
openssh.xml
opensshd.init
survey.sh
**/*.0
**/*.o
**/*.out
**/*.a
autom4te.cache/
scp
sftp
sftp-server
ssh
ssh-add
ssh-agent
ssh-keygen
ssh-keyscan
ssh-keysign
ssh-pkcs11-helper
sshd
!regress/misc/fuzz-harness/Makefile
+tags
diff --git a/.skipped-commit-ids b/.skipped-commit-ids
index f1b3b7640a3f..01d447a49c43 100644
--- a/.skipped-commit-ids
+++ b/.skipped-commit-ids
@@ -1,33 +1,34 @@
5317f294d63a876bfc861e19773b1575f96f027d remove libssh from makefiles
a337e886a49f96701ccbc4832bed086a68abfa85 Makefile changes
f2c9feb26963615c4fece921906cf72e248b61ee more Makefile
fa728823ba21c4b45212750e1d3a4b2086fd1a62 more Makefile refactoring
1de0e85522051eb2ffa00437e1885e9d7b3e0c2e moduli update
814b2f670df75759e1581ecef530980b2b3d7e0f remove redundant make defs
04431e8e7872f49a2129bf080a6b73c19d576d40 moduli update
+c07772f58028fda683ee6abd41c73da3ff70d403 moduli update
Old upstream tree:
321065a95a7ccebdd5fd08482a1e19afbf524e35 Update DH groups
d4f699a421504df35254cf1c6f1a7c304fb907ca Remove 1k bit groups
aafe246655b53b52bc32c8a24002bc262f4230f7 Remove intermediate moduli
8fa9cd1dee3c3339ae329cf20fb591db6d605120 put back SSH1 for 6.9
f31327a48dd4103333cc53315ec53fe65ed8a17a Generate new moduli
edbfde98c40007b7752a4ac106095e060c25c1ef Regen moduli
052fd565e3ff2d8cec3bc957d1788f50c827f8e2 Switch to tame-based sandbox
7cf73737f357492776223da1c09179fa6ba74660 Remove moduli <2k
180d84674be1344e45a63990d60349988187c1ae Update moduli
f6ae971186ba68d066cd102e57d5b0b2c211a5ee systrace is dead.
96c5054e3e1f170c6276902d5bc65bb3b87a2603 remove DEBUGLIBS from Makefile
6da9a37f74aef9f9cc639004345ad893cad582d8 Update moduli file
77bcb50e47b68c7209c7f0a5a020d73761e5143b unset REGRESS_FAIL_EARLY
38c2133817cbcae75c88c63599ac54228f0fa384 Change COMPILER_VERSION tests
30c20180c87cbc99fa1020489fe7fd8245b6420c resync integrity.sh shell
1e6b51ddf767cbad0a4e63eb08026c127e654308 integrity.sh reliability
fe5b31f69a60d47171836911f144acff77810217 Makefile.inc bits
5781670c0578fe89663c9085ed3ba477cf7e7913 Delete sshconnect1.c
ea80f445e819719ccdcb237022cacfac990fdc5c Makefile.inc warning flags
b92c93266d8234d493857bb822260dacf4366157 moduli-gen.sh tweak
b25bf747544265b39af74fe0716dc8d9f5b63b95 Updated moduli
1bd41cba06a7752de4df304305a8153ebfb6b0ac rsa.[ch] already removed
e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604 Makefile changes
diff --git a/ChangeLog b/ChangeLog
index 0307f62e0557..fdc0a0619c63 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9706 +1,10342 @@
-commit aede1c34243a6f7feae2fb2cb686ade5f9be6f3d
+commit fd0fa130ecf06d7d092932adcd5d77f1549bfc8d
Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 17 11:01:20 2018 +1100
+Date: Thu Apr 18 08:52:57 2019 +1000
- Require OpenSSL 1.1.x series 1.1.0g or greater
+ makedepend
+
+commit 5de397a876b587ba05a9169237deffdc71f273b0
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Apr 5 11:29:51 2019 -0700
+
+ second thoughts: leave README in place
- Previous versions have a bug with EVP_CipherInit() when passed a
- NULL EVP_CIPHER, per https://github.com/openssl/openssl/pull/4613
+ A number of contrib/* files refer to the existing README so let's leave
+ it in place for release and add the new markdown version in parallel.
- ok dtucker@
+ I'll get rid of README after release.
-commit 08300c211409c212e010fe2e2f2883e573a04ce2
+commit 5d3127d9274519b25ed10e320f45045ba8d7f3be
Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 17 08:12:02 2018 +1100
+Date: Fri Apr 5 11:29:31 2019 -0700
- unbreak compilation with --with-ssl-engine
+ Revert "rewrite README"
- Missing last argument to OPENSSL_init_crypto()
+ This reverts commit 9444d82678cb7781820da4d1c23b3c2b9fb1e12f.
-commit 1673274aee67ce0eb6f00578b6f3d2bcbd58f937
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Oct 16 14:45:57 2018 +1100
+commit 9444d82678cb7781820da4d1c23b3c2b9fb1e12f
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Apr 5 11:21:48 2019 -0700
- Remove gcc spectre mitigation flags.
+ rewrite README
- Current impementions of the gcc spectre mitigation flags cause
- miscompilations when combined with other flags and do not provide much
- protection. Found by fweimer at redhat.com, ok djm@
+ Include basic build instructions and comments on commonly-used build-
+ time flags, links to the manual pages and other resources.
+
+ Now in Markdown format for better viewing on github, etc.
-commit 4e23deefd7959ef83c73ed9cce574423438f6133
+commit a924de0c4908902433813ba205bee1446bd1a157
Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 16 10:51:52 2018 +1100
+Date: Fri Apr 5 03:41:52 2019 +1100
- Avoid deprecated OPENSSL_config when using 1.1.x
+ update versions
+
+commit 312dcee739bca5d6878c536537b2a8a497314b75
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Apr 3 15:48:45 2019 +0000
+
+ upstream: openssh-8.0
- OpenSSL 1.1.x soft-deprecated OPENSSL_config in favour of
- OPENSSL_init_crypto; pointed out by Jakub Jelen
+ OpenBSD-Commit-ID: 5aafdf218679dab982fea20771afd643be9a127b
-commit 797cdd9c8468ed1125ce60d590ae3f1397866af4
+commit 885bc114692046d55e2a170b932bdc0092fa3456
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Apr 4 02:47:40 2019 +1100
+
+ session: Do not use removed API
+
+ from Jakub Jelen
+
+commit 9d7b2882b0c9a5e9bf8312ce4075bf178e2b98be
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Mar 29 11:31:40 2019 +0000
+
+ upstream: when logging/fataling on error, include a bit more detail
+
+ than just the function name and the error message
+
+ OpenBSD-Commit-ID: dd72d7eba2215fcb89be516c378f633ea5bcca9f
+
+commit 79a87d32783d6c9db40af8f35e091d9d30365ae7
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Oct 12 16:58:47 2018 +1100
+Date: Wed Apr 3 06:27:45 2019 +1100
- Don't avoid our *sprintf replacements.
+ Remove "struct ssh" from sys_auth_record_login.
- Don't let systems with broken printf(3) avoid our replacements
- via asprintf(3)/vasprintf(3) calling libc internally. From djm@
+ It's not needed, and is not available from the call site in loginrec.c
+ Should only affect AIX, spotted by Kevin Brott.
-commit e526127cbd2f8ad88fb41229df0c9b850c722830
+commit 138c0d52cdc90f9895333b82fc57d81cce7a3d90
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Oct 12 16:43:35 2018 +1100
+Date: Tue Apr 2 18:21:35 2019 +1100
- Check if snprintf understands %zu.
+ Adapt custom_failed_login to new prototype.
- If the platforms snprintf and friends don't understand %zu, use the
- compat replacement. Prevents segfaults on those platforms.
+ Spotted by Kevin Brott.
-commit cf39f875191708c5f2f1a3c1c9019f106e74aea3
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 12 09:48:05 2018 +1100
+commit a0ca4009ab2f0b1007ec8ab6864dbf9b760a8ed5
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Apr 1 20:07:23 2019 +1100
- remove stale link, tweak
+ Add includes.h for compat layer.
+
+ Should fix build on AIX 7.2.
-commit a7205e68decf7de2005810853b4ce6b222b65e2a
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 12 09:47:20 2018 +1100
+commit 00991151786ce9b1d577bdad1f83a81d19c8236d
+Author: Tim Rice <tim@multitalents.net>
+Date: Sun Mar 31 22:14:22 2019 -0700
- update version numbers ahead of release
+ Stop USL compilers for erroring with "integral constant expression expected"
-commit 1a4a9cf80f5b92b9d1dadd0bfa8867c04d195391
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 11 03:48:04 2018 +0000
+commit 43f47ebbdd4037b569c23b8f4f7981f53b567f1d
+Author: Tim Rice <tim@multitalents.net>
+Date: Sun Mar 31 19:22:19 2019 -0700
- upstream: don't send new-style rsa-sha2-*-cert-v01@openssh.com names to
-
- older OpenSSH that can't handle them. spotted by Adam Eijdenberg; ok dtucker
-
- OpenBSD-Commit-ID: 662bbc402e3d7c9b6c322806269698106a6ae631
+ Only use O_NOFOLLOW in fchownat and fchmodat if defined
-commit dc8ddcdf1a95e011c263486c25869bb5bf4e30ec
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 11 13:08:59 2018 +1100
+commit 342d6e51589b184c337cccfc4c788b60ff8b3765
+Author: Jakub Jelen <jjelen@redhat.com>
+Date: Fri Mar 29 12:29:41 2019 +0100
- update depends
+ Adjust softhsm2 path on Fedora Linux for regress
+
+ The SoftHSM lives in Fedora in /usr/lib64/pkcs11/libsofthsm2.so
-commit 26841ac265603fd2253e6832e03602823dbb4022
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 11 13:02:11 2018 +1100
+commit f5abb05f8c7358dacdcb866fe2813f6d8efd5830
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Mar 28 09:26:14 2019 +1100
- some more duplicated key algorithm lines
+ Only use O_NOFOLLOW in utimensat if defined.
- From Adam Eijdenberg
+ Fixes build on systems that don't have it (Solaris <=9) Found by
+ Tom G. Christensen.
-commit 5d9d17603bfbb620195a4581025052832b4c4adc
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 11 11:56:36 2018 +1100
+commit 786cd4c1837fdc3fe7b4befe54a3f37db7df8715
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Wed Mar 27 18:18:21 2019 +0100
- fix duplicated algorithm specification lines
+ drop old Cygwin considerations
- Spotted by Adam Eijdenberg
+ - Cygwin supports non-DOS characters in filenames
+ - Cygwin does not support Windows XP anymore
+
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
-commit ebfafd9c7a5b2a7fb515ee95dbe0e44e11d0a663
+commit 21da87f439b48a85b951ef1518fe85ac0273e719
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 11 00:52:46 2018 +0000
+Date: Wed Mar 27 09:29:14 2019 +0000
- upstream: typo in plain RSA algorithm counterpart names for
+ upstream: fix interaction between ClientAliveInterval and RekeyLimit
- certificates; spotted by Adam Eijdenberg; ok dtucker@
+ that could cause connection to close incorrectly; Report and patch from Jakub
+ Jelen in bz#2757; ok dtucker@ markus@
- OpenBSD-Commit-ID: bfcdeb6f4fc9e7607f5096574c8f118f2e709e00
+ OpenBSD-Commit-ID: 17229a8a65bd8e6c2080318ec2b7a61e1aede3fb
-commit c29b111e7d87c2324ff71c80653dd8da168c13b9
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 11 11:29:35 2018 +1100
+commit 4f0019a9afdb4a94d83b75e82dbbbe0cbe826c56
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Mar 25 22:34:52 2019 +0000
- check pw_passwd != NULL here too
+ upstream: Fix authentication failures when "AuthenticationMethods
- Again, for systems with broken NIS implementations.
+ any" in a Match block overrides a more restrictive global default.
- Prompted by coolbugcheckers AT gmail.com
+ Spotted by jmc@, ok markus@
+
+ OpenBSD-Commit-ID: a90a4fe2ab81d0eeeb8fdfc21af81f7eabda6666
-commit fe8e8f349a553ef4c567acd418aac769a82b7729
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 11 11:03:15 2018 +1100
+commit d6e5def308610f194c0ec3ef97a34a3e9630e190
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Mar 25 22:33:44 2019 +0000
- check for NULL return from shadow_pw()
+ upstream: whitespace
- probably unreachable on this platform; pointed out by
- coolbugcheckers AT gmail.com
+ OpenBSD-Commit-ID: 106e853ae8a477e8385bc53824d3884a8159db07
-commit acc59cbe7a1fb169e1c3caba65a39bd74d6e030d
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed Oct 10 16:43:49 2018 +0000
+commit 26e0cef07b04479537c971dec898741df1290fe5
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Mar 25 16:19:44 2019 +0000
- upstream: introducing openssh 7.9
+ upstream: Expand comment to document rationale for default key
- OpenBSD-Commit-ID: 42d526a9fe01a40dd299ac58014d3349adf40e25
+ sizes. "seems worthwhile" deraadt.
+
+ OpenBSD-Commit-ID: 72e5c0983d7da1fb72f191870f36cb58263a2456
-commit 12731158c75c8760a8bea06350eeb3e763fe1a07
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Oct 11 10:29:29 2018 +1100
+commit f47269ea67eb4ff87454bf0d2a03e55532786482
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Mar 25 15:49:00 2019 +0000
- supply callback to PEM_read_bio_PrivateKey
-
- OpenSSL 1.1.0i has changed the behaviour of their PEM APIs,
- so that empty passphrases are interpreted differently. This
- probabalistically breaks loading some keys, because the PEM format
- is terrible and doesn't include a proper MAC.
+ upstream: Increase the default RSA key size to 3072 bits. Based on
- Avoid this by providing a basic callback to avoid passing empty
- passphrases to OpenSSL in cases where one is required.
+ the estimates from NIST Special Publication 800-57, 3k bits provides security
+ equivalent to 128 bits which is the smallest symmetric cipher we enable by
+ default. ok markus@ deraadt@
- Based on patch from Jakub Jelen in bz#2913; ok dtucker@
+ OpenBSD-Commit-ID: 461dd32ebe808f88f4fc3ec74749b0e6bef2276b
-commit d1d301a1dd5d6cc3a9ed93ab7ab09dda4cb456e0
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 10 14:57:00 2018 +1100
+commit 62949c5b37af28d8490d94866e314a76be683a5e
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Mar 22 20:58:34 2019 +0000
- in pick_salt() avoid dereference of NULL passwords
+ upstream: full stop in the wrong place;
- Apparently some NIS implementations can leave pw->pw_passwd (or the
- shadow equivalent) NULL.
+ OpenBSD-Commit-ID: 478a0567c83553a2aebf95d0f1bd67ac1b1253e4
+
+commit 1b1332b5bb975d759a50b37f0e8bc8cfb07a0bb0
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Mar 16 19:14:21 2019 +0000
+
+ upstream: benno helped me clean up the tcp forwarding section;
- bz#2909; based on patch from Todd Eigenschink
+ OpenBSD-Commit-ID: d4bec27edefde636fb632b7f0b7c656b9c7b7f08
-commit edbb6febccee084d212fdc0cb05b40cb1c646ab1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Oct 9 05:42:23 2018 +0000
+commit 2aee9a49f668092ac5c9d34e904ef7a9722e541d
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Fri Mar 8 17:24:43 2019 +0000
- upstream: Treat all PEM_read_bio_PrivateKey() errors when a passphrase
+ upstream: fix use-after-free in ssh-pkcs11; found by hshoexer w/AFL
- is specified as "incorrect passphrase" instead of trying to choose between
- that and "invalid format".
+ OpenBSD-Commit-ID: febce81cca72b71f70513fbee4ff52ca050f675c
+
+commit 9edbd7821e6837e98e7e95546cede804dac96754
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Mar 14 10:17:28 2019 +1100
+
+ Fix build when configured --without-openssl.
- libcrypto can return ASN1 parsing errors rather than the expected
- decrypt error in certain infrequent cases when trying to decrypt/parse
- PEM private keys when supplied with an invalid passphrase.
+ ok djm@
+
+commit 825ab32f0d04a791e9d19d743c61ff8ed9b4d8e5
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Mar 14 08:51:17 2019 +1100
+
+ On Cygwin run sshd as SYSTEM where possible.
- Report and repro recipe from Thomas Deutschmann in bz#2901
+ Seteuid now creates user token using S4U. We don't create a token
+ from scratch anymore, so we don't need the "Create a process token"
+ privilege. The service can run under SYSTEM again...
- ok markus@
+ ...unless Cygwin is running on Windows Vista or Windows 7 in the
+ WOW64 32 bit emulation layer. It turns out that WOW64 on these systems
+ didn't implement MsV1_0 S4U Logon so we still need the fallback
+ to NtCreateToken for these systems.
- OpenBSD-Commit-ID: b1d4cd92395f9743f81c0d23aab2524109580870
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
-commit 2581333d564d8697837729b3d07d45738eaf5a54
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Fri Oct 5 14:26:09 2018 +0000
+commit a212107bfdf4d3e870ab7a443e4d906e5b9578c3
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Wed Mar 13 10:49:16 2019 +1100
- upstream: Support using service names for port numbers.
-
- * Try to resolve a port specification with getservbyname(3) if a
- numeric conversion fails.
- * Make the "Port" option in ssh_config handle its argument as a
- port rather than a plain integer.
+ Replace alloca with xcalloc.
- ok dtucker@ deraadt@
+ The latter checks for memory exhaustion and integer overflow and may be
+ at a less predictable place. Sanity check by vinschen at redhat.com, ok
+ djm@
+
+commit daa7505aadca68ba1a2c70cbdfce423208eb91ee
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Mar 12 09:19:19 2019 +1100
+
+ Use Cygwin-specific matching only for users+groups.
- OpenBSD-Commit-ID: e7f03633133205ab3dfbc67f9df7475fabae660d
+ Patch from vinschen at redhat.com, updated a little by me.
-commit e0d6501e86734c48c8c503f81e1c0926e98c5c4c
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 4 07:47:35 2018 +0000
+commit fd10cf027b56f9aaa80c9e3844626a05066589a4
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Mar 6 22:14:23 2019 +0000
- upstream: when the peer sends a channel-close message, make sure we
+ upstream: Move checks for lists of users or groups into their own
- close the local extended read fd (stderr) along with the regular read fd
- (stdout). Avoids weird stuck processed in multiplexing mode.
+ function. This is a no-op on OpenBSD but will make things easier in
+ -portable, eg on systems where these checks should be case-insensitive. ok
+ djm@
- Report and analysis by Nelson Elhage and Geoffrey Thomas in bz#2863
+ OpenBSD-Commit-ID: 8bc9c8d98670e23f8eaaaefe29c1f98e7ba0487e
+
+commit ab5fee8eb6a011002fd9e32b1597f02aa8804a25
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Mar 6 21:06:59 2019 +0000
+
+ upstream: Reset last-seen time when sending a keepalive. Prevents
- ok dtucker@ markus@
+ sending two keepalives successively and prematurely terminating connection
+ when ClientAliveCount=1. While there, collapse two similar tests into one.
+ ok markus@
- OpenBSD-Commit-ID: a48a2467fe938de4de69d2e7193d5fa701f12ae9
+ OpenBSD-Commit-ID: 043670d201dfe222537a2a4bed16ce1087de5ddd
-commit 6f1aabb128246f445e33b8844fad3de9cb1d18cb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 4 01:04:52 2018 +0000
+commit c13b74530f9f1d9df7aeae012004b31b2de4438e
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Tue Mar 5 16:17:12 2019 +0000
- upstream: factor out channel status formatting from
+ upstream: PKCS#11 support is no longer limited to RSA; ok benno@
- channel_open_message() so we can use it in other debug messages
+ kn@
- OpenBSD-Commit-ID: 9c3903ca28fcabad57f566c9d0045b41ab7d52ba
+ OpenBSD-Commit-ID: 1a9bec64d530aed5f434a960e7515a3e80cbc826
-commit f1dd179e122bdfdb7ca3072d9603607740efda05
+commit e9552d6043db7cd170ac6ba1b4d2c7a5eb2c3201
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 4 00:10:11 2018 +0000
+Date: Fri Mar 1 03:29:32 2019 +0000
- upstream: include a little more information about the status and
+ upstream: in ssh_set_newkeys(), mention the direction that we're
- disposition of channel's extended (stderr) fd; makes debugging some things a
- bit easier. No behaviour change.
+ keying in debug messages. Previously it would be difficult to tell which
+ direction it was talking about
- OpenBSD-Commit-ID: 483eb6467dc7d5dbca8eb109c453e7a43075f7ce
+ OpenBSD-Commit-ID: c2b71bfcceb2a7389b9d0b497fb2122a406a522d
-commit 2d1428b11c8b6f616f070f2ecedce12328526944
+commit 76a24b3fa193a9ca3e47a8779d497cb06500798b
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 4 00:04:41 2018 +0000
+Date: Fri Mar 1 02:32:39 2019 +0000
- upstream: explicit_bzero here to be consistent with other kex*.c;
+ upstream: Fix two race conditions in sshd relating to SIGHUP:
- report from coolbugcheckers AT gmail.com
+ 1. Recently-forked child processes will briefly remain listening to
+ listen_socks. If the main server sshd process completes its restart
+ via execv() before these sockets are closed by the child processes
+ then it can fail to listen at the desired addresses/ports and/or
+ fail to restart.
- OpenBSD-Commit-ID: a90f146c5b5f5b1408700395e394f70b440856cb
+ 2. When a SIGHUP is received, there may be forked child processes that
+ are awaiting their reexecution state. If the main server sshd
+ process restarts before passing this state, these child processes
+ will yield errors and use a fallback path of reading the current
+ sshd_config from the filesystem rather than use the one that sshd
+ was started with.
+
+ To fix both of these cases, we reuse the startup_pipes that are shared
+ between the main server sshd and forked children. Previously this was
+ used solely to implement tracking of pre-auth child processes for
+ MaxStartups, but this extends the messaging over these pipes to include
+ a child->parent message that the parent process is safe to restart. This
+ message is sent from the child after it has completed its preliminaries:
+ closing listen_socks and receiving its reexec state.
+
+ bz#2953, reported by Michal Koutný; ok markus@ dtucker@
+
+ OpenBSD-Commit-ID: 7df09eacfa3ce13e9a7b1e9f17276ecc924d65ab
-commit 5eff5b858e717e901e6af6596306a114de9f79f2
+commit de817e9dfab99473017d28cdf69e60397d00ea21
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 3 06:38:35 2018 +0000
+Date: Fri Mar 1 02:16:47 2019 +0000
- upstream: Allow ssh_config IdentityAgent directive to accept
+ upstream: mention PKCS11Provide=none, reword a little and remove
- environment variable names as well as explicit paths. ok dtucker@
+ mention of RSA keys only (since we support ECDSA now and might support others
+ in the future). Inspired by Jakub Jelen via bz#2974
- OpenBSD-Commit-ID: 2f0996e103876c53d8c9dd51dcce9889d700767b
+ OpenBSD-Commit-ID: a92e3686561bf624ccc64ab320c96c9e9a263aa5
-commit a46ac4d86b25414d78b632e8173578b37e5f8a83
+commit 95a8058c1a90a27acbb91392ba206854abc85226
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Oct 2 12:51:58 2018 +0000
+Date: Fri Mar 1 02:08:50 2019 +0000
- upstream: mention INFO@openssh.com for sending SIGINFO
+ upstream: let PKCS11Provider=none do what users expect
- OpenBSD-Commit-ID: 132471eeb0df658210afd27852fe65131b26e900
+ print PKCS11Provider instead of obsolete SmartcardDevice in config dump.
+
+ bz#2974 ok dtucker@
+
+ OpenBSD-Commit-ID: c303d6f0230a33aa2dd92dc9b68843d56a64f846
-commit ff3a411cae0b484274b7900ef52ff4dad3e12876
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 2 22:49:40 2018 +1000
+commit 8e7bac35aa576d2fd7560836da83733e864ce649
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed Feb 27 19:37:01 2019 +0000
- only support SIGINFO on systems with SIGINFO
+ upstream: dup stdout/in for proxycommand=-, otherwise stdout might
+
+ be redirected to /dev/null; ok djm@
+
+ OpenBSD-Commit-ID: 97dfce4c47ed4055042de8ebde85b7d88793e595
-commit cd98925c6405e972dc9f211afc7e75e838abe81c
+commit 9b61130fbd95d196bce81ebeca94a4cb7c0d5ba0
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Oct 2 12:40:07 2018 +0000
+Date: Sat Feb 23 08:20:43 2019 +0000
- upstream: Add server support for signalling sessions via the SSH
+ upstream: openssh-7.9 accidentally reused the server's algorithm lists
- channel/ session protocol. Signalling is only supported to sesssions that are
- not subsystems and were not started with a forced command.
+ in the client for KEX, ciphers and MACs. The ciphers and MACs were identical
+ between the client and server, but the error accidentially disabled the
+ diffie-hellman-group-exchange-sha1 KEX method.
- Long requested in bz#1424
+ This fixes the client code to use the correct method list, but
+ because nobody complained, it also disables the
+ diffie-hellman-group-exchange-sha1 KEX method.
- Based on a patch from markus@ and reworked by dtucker@;
- ok markus@ dtucker@
+ Reported by nuxi AT vault24.org via bz#2697; ok dtucker
- OpenBSD-Commit-ID: 4bea826f575862eaac569c4bedd1056a268be1c3
+ OpenBSD-Commit-ID: e30c33a23c10fd536fefa120e86af1842e33fd57
-commit dba50258333f2604a87848762af07ba2cc40407a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 26 07:32:44 2018 +0000
+commit 37638c752041d591371900df820f070037878a2d
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Wed Feb 20 13:41:25 2019 +0100
- upstream: remove big ugly TODO comment from start of file. Some of
+ Cygwin: implement case-insensitive Unicode user and group name matching
- the mentioned tasks are obsolete and, of the remainder, most are already
- captured in PROTOCOL.mux where they better belong
+ The previous revert enabled case-insensitive user names again. This
+ patch implements the case-insensitive user and group name matching.
+ To allow Unicode chars, implement the matcher using wchar_t chars in
+ Cygwin-specific code. Keep the generic code changes as small as possible.
+ Cygwin: implement case-insensitive Unicode user and group name matching
- OpenBSD-Commit-ID: 16d9d76dee42a5bb651c9d6740f7f0ef68aeb407
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
-commit 92b61a38ee9b765f5049f03cd1143e13f3878905
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 26 07:30:05 2018 +0000
+commit bed1d43698807a07bb4ddb93a46b0bd84b9970b3
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Feb 22 15:21:21 2019 +1100
- upstream: Document mux proxy mode; added by Markus in openssh-7.4
-
- Also add a little bit of information about the overall packet format
-
- OpenBSD-Commit-ID: bdb6f6ea8580ef96792e270cae7857786ad84a95
+ Revert unintended parts of previous commit.
-commit 9d883a1ce4f89b175fd77405ff32674620703fb2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 26 01:48:57 2018 +0000
+commit f02afa350afac1b2f2d1413259a27a4ba1e2ca24
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Wed Feb 20 13:41:24 2019 +0100
- upstream: s/process_mux_master/mux_master_process/ in mux master
-
- function names,
+ Revert "[auth.c] On Cygwin, refuse usernames that have differences in case"
- Gives better symmetry with the existing mux_client_*() names and makes
- it more obvious when a message comes from the master vs client (they
- are interleved in ControlMaster=auto mode).
+ This reverts commit acc9b29486dfd649dfda474e5c1a03b317449f1c.
- no functional change beyond prefixing a could of log messages with
- __func__ where they were previously lacking.
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
+
+commit 4c55b674835478eb80a1a7aeae588aa654e2a433
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Sat Feb 16 14:13:43 2019 +0100
+
+ Add tags to .gitignore
- OpenBSD-Commit-ID: b01f7c3fdf92692e1713a822a89dc499333daf75
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
-commit c2fa53cd6462da82d3a851dc3a4a3f6b920337c8
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Sep 22 14:41:24 2018 +1000
+commit 625b62634c33eaef4b80d07529954fe5c6435fe5
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Feb 22 03:37:11 2019 +0000
- Remove unused variable in _ssh_compat_fflush.
+ upstream: perform removal of agent-forwarding directory in forward
+
+ setup error path with user's privileged. This is a no-op as this code always
+ runs with user privilege now that we no longer support running sshd with
+ privilege separation disabled, but as long as the privsep skeleton is there
+ we should follow the rules.
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset=UTF-8
+ Content-Transfer-Encoding: 8bit
+
+ bz#2969 with patch from Erik Sjölund
+
+ OpenBSD-Commit-ID: 2b708401a5a8d6133c865d7698d9852210dca846
-commit d1b3540c21212624af907488960d703c7d987b42
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Sep 20 18:08:43 2018 +1000
+commit d9ecfaba0b2f1887d20e4368230632e709ca83be
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Mon Feb 18 07:02:34 2019 +0000
- Import updated moduli.
+ upstream: sync the description of ~/.ssh/config with djm's updated
+
+ description in ssh.1; issue pointed out by andreas kahari
+
+ ok dtucker djm
+
+ OpenBSD-Commit-ID: 1b01ef0ae2c6328165150badae317ec92e52b01c
-commit b5e412a8993ad17b9e1141c78408df15d3d987e1
+commit 38e83e4f219c752ebb1560633b73f06f0392018b
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 21 12:46:22 2018 +0000
+Date: Tue Feb 12 23:53:10 2019 +0000
- upstream: Allow ssh_config ForwardX11Timeout=0 to disable the
+ upstream: fix regression in r1.302 reported by naddy@ - only the first
- timeout and allow X11 connections in untrusted mode indefinitely. ok dtucker@
+ public key from the agent was being attempted for use.
- OpenBSD-Commit-ID: ea1ceed3f540b48e5803f933e59a03b20db10c69
+ OpenBSD-Commit-ID: 07116aea521a04888718b2157f1ca723b2f46c8d
-commit cb24d9fcc901429d77211f274031653476864ec6
+commit 5c68ea8da790d711e6dd5f4c30d089c54032c59a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 21 12:23:17 2018 +0000
+Date: Mon Feb 11 09:44:42 2019 +0000
- upstream: when compiled with GSSAPI support, cache supported method
+ upstream: cleanup GSSAPI authentication context after completion of the
- OIDs by calling ssh_gssapi_prepare_supported_oids() regardless of whether
- GSSAPI authentication is enabled in the main config.
+ authmethod. Move function-static GSSAPI state to the client Authctxt
+ structure. Make static a bunch of functions that aren't used outside this
+ file.
- This avoids sandbox violations for configurations that enable GSSAPI
- auth later, e.g.
+ Based on patch from Markus Schmidt <markus@blueflash.cc>; ok markus@
- Match user djm
- GSSAPIAuthentication yes
+ OpenBSD-Commit-ID: 497fb792c0ddb4f1ba631b6eed526861f115dbe5
+
+commit a8c807f1956f81a92a758d3d0237d0ff06d0be5d
+Author: benno@openbsd.org <benno@openbsd.org>
+Date: Sun Feb 10 16:35:41 2019 +0000
+
+ upstream: ssh-keygen -D pkcs11.so needs to initialize pkcs11
- bz#2107; ok dtucker@
+ interactive, so it can ask for the smartcards PIN. ok markus@
- OpenBSD-Commit-ID: a5dd42d87c74e27cfb712b15b0f97ab20e0afd1d
+ OpenBSD-Commit-ID: 1be7ccf88f1876e0fc4d7c9b3f96019ac5655bab
-commit bbc8af72ba68da014d4de6e21a85eb5123384226
+commit 3d896c157c722bc47adca51a58dca859225b5874
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 21 12:20:12 2018 +0000
+Date: Sun Feb 10 11:15:52 2019 +0000
- upstream: In sshkey_in_file(), ignore keys that are considered for
+ upstream: when checking that filenames sent by the server side
- being too short (i.e. SSH_ERR_KEY_LENGTH). These keys will not be considered
- to be "in the file". This allows key revocation lists to contain short keys
- without the entire revocation list being considered invalid.
+ match what the client requested, be prepared to handle shell-style brace
+ alternations, e.g. "{foo,bar}".
- bz#2897; ok dtucker
+ "looks good to me" millert@ + in snaps for the last week courtesy
+ deraadt@
- OpenBSD-Commit-ID: d9f3d857d07194a42ad7e62889a74dc3f9d9924b
+ OpenBSD-Commit-ID: 3b1ce7639b0b25b2248e3a30f561a548f6815f3e
-commit 383a33d160cefbfd1b40fef81f72eadbf9303a66
+commit 318e4f8548a4f5c0c913f61e27d4fc21ffb1eaae
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 21 03:11:36 2018 +0000
+Date: Sun Feb 10 11:10:57 2019 +0000
- upstream: Treat connections with ProxyJump specified the same as ones
+ upstream: syslog when connection is dropped for attempting to run a
- with a ProxyCommand set with regards to hostname canonicalisation (i.e. don't
- try to canonicalise the hostname unless CanonicalizeHostname is set to
- 'always').
+ command when ForceCommand=internal-sftp is in effect; bz2960; ok dtucker@
- Patch from Sven Wegener via bz#2896
+ OpenBSD-Commit-ID: 8c87fa66d7fc6c0fffa3a3c28e8ab5e8dde234b8
+
+commit 2ff2e19653b8c0798b8b8eff209651bdb1be2761
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Feb 8 14:53:35 2019 +1100
+
+ don't set $MAIL if UsePam=yes
- OpenBSD-Commit-ID: 527ff501cf98bf65fb4b29ed0cb847dda10f4d37
+ PAM typically specifies the user environment if it's enabled, so don't
+ second guess. bz#2937; ok dtucker@
-commit 0cbed248ed81584129b67c348dbb801660f25a6a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 20 23:40:16 2018 +0000
+commit 03e92dd27d491fe6d1a54e7b2f44ef1b0a916e52
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Feb 8 14:50:36 2019 +1100
- upstream: actually make CASignatureAlgorithms available as a config
+ use same close logic for stderr as stdout
- option
+ Avoids sending SIGPIPE to child processes after their parent exits
+ if they attempt to write to stderr.
- OpenBSD-Commit-ID: 93fa7ff58314ed7b1ab7744090a6a91232e6ae52
+ Analysis and patch from JD Paul; patch reworked by Jakub Jelen and
+ myself. bz#2071; ok dtucker@
-commit 62528870c0ec48cd86a37dd7320fb85886c3e6ee
+commit 8c53d409baeeaf652c0c125a9b164edc9dbeb6de
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Sep 20 08:07:03 2018 +0000
+Date: Tue Feb 5 11:35:56 2019 +0000
- upstream: Import updated moduli.
+ upstream: Adapt code in the non-USE_PIPES codepath to the new packet
- OpenBSD-Commit-ID: 04431e8e7872f49a2129bf080a6b73c19d576d40
+ API. This code is not normally reachable since USE_PIPES is always defined.
+ bz#2961, patch from adrian.fita at gmail com.
+
+ OpenBSD-Commit-ID: 8d8428d678d1d5eb4bb21921df34e8173e6d238a
-commit e6933a2ffa0659d57f3c7b7c457b2c62b2a84613
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Thu Sep 20 06:58:48 2018 +0000
+commit 7a7fdca78de4b4774950be056099e579ef595414
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Feb 4 23:37:54 2019 +0000
- upstream: reorder CASignatureAlgorithms, and add them to the
+ upstream: fix NULL-deref crash in PKCS#11 code when attempting
- various -o lists; ok djm
+ login to a token requiring a PIN; reported by benno@ fix mostly by markus@
- OpenBSD-Commit-ID: ecb88baecc3c54988b4d1654446ea033da359288
+ OpenBSD-Commit-ID: 438d0b114b1b4ba25a9869733db1921209aa9a31
-commit aa083aa9624ea7b764d5a81c4c676719a1a3e42b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 20 03:31:49 2018 +0000
+commit cac302a4b42a988e54d32eb254b29b79b648dbf5
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Feb 4 02:39:42 2019 +0000
- upstream: fix "ssh -Q sig" to show correct signature algorithm list
+ upstream: Remove obsolete "Protocol" from commented out examples. Patch
- (it was erroneously showing certificate algorithms); prompted by markus@
+ from samy.mahmoudi at gmail com.
- OpenBSD-Commit-ID: 1cdee002f2f0c21456979deeb887fc889afb154d
+ OpenBSD-Commit-ID: 16aede33dae299725a03abdac5dcb4d73f5d0cbf
-commit ecac7e1f7add6b28874959a11f2238d149dc2c07
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 20 03:30:44 2018 +0000
+commit 483b3b638500fd498b4b529356e5a0e18cf76891
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Feb 1 03:52:23 2019 +0000
- upstream: add CASignatureAlgorithms option for the client, allowing
+ upstream: Save connection timeout and restore for 2nd and
- it to specify which signature algorithms may be used by CAs when signing
- certificates. Useful if you want to ban RSA/SHA1; ok markus@
+ subsequent attempts, preventing them from having no timeout. bz#2918, ok
+ djm@
- OpenBSD-Commit-ID: 9159e5e9f67504829bf53ff222057307a6e3230f
+ OpenBSD-Commit-ID: 4977f1d0521d9b6bba0c9a20d3d226cefac48292
-commit 86e5737c39153af134158f24d0cab5827cbd5852
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 20 03:28:06 2018 +0000
+commit 5f004620fdc1b2108139300ee12f4014530fb559
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed Jan 30 19:51:15 2019 +0000
- upstream: Add sshd_config CASignatureAlgorithms option to allow
-
- control over which signature algorithms a CA may use when signing
- certificates. In particular, this allows a sshd to ban certificates signed
- with RSA/SHA1.
+ upstream: Add authors for public domain sntrup4591761 code;
- ok markus@
+ confirmed by Daniel J. Bernstein
- OpenBSD-Commit-ID: b05c86ef8b52b913ed48d54a9b9c1a7714d96bac
+ OpenBSD-Commit-ID: b4621f22b8b8ef13e063c852af5e54dbbfa413c1
-commit f80e68ea7d62e2dfafc12f1a60ab544ae4033a0f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 19 02:03:02 2018 +0000
+commit 2c21b75a7be6ebdcbceaebb43157c48dbb36f3d8
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sun Jan 27 07:14:11 2019 +0000
- upstream: Make "ssh-add -q" do what it says on the tin: silence
+ upstream: add -T to usage();
- output from successful operations.
+ OpenBSD-Commit-ID: a7ae14d9436c64e1bd05022329187ea3a0ce1899
+
+commit 19a0f0529d3df04118da829528cac7ceff380b24
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jan 28 03:50:39 2019 +0000
+
+ upstream: The test sshd_config in in $OBJ.
- Based on patch from Thijs van Dijk; ok dtucker@ deraadt@
+ OpenBSD-Regress-ID: 1e5d908a286d8e7de3a15a0020c8857f3a7c9172
+
+commit 8fe25440206319d15b52d12b948a5dfdec14dca3
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jan 28 03:28:10 2019 +0000
+
+ upstream: Remove leftover debugging.
- OpenBSD-Commit-ID: c4f754ecc055c10af166116ce7515104aa8522e1
+ OpenBSD-Regress-ID: 3d86c3d4867e46b35af3fd2ac8c96df0ffdcfeb9
-commit 5e532320e9e51de720d5f3cc2596e95d29f6e98f
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Mon Sep 17 15:40:14 2018 +0000
+commit e30d32364d12c351eec9e14be6c61116f9d6cc90
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jan 28 00:12:36 2019 +0000
- upstream: When choosing a prime from the moduli file, avoid
+ upstream: Enable ssh-dss for the agent test. Disable it for the
- re-using the linenum variable for something that is not a line number to
- avoid the confusion that resulted in the bug in rev. 1.64. This also lets us
- pass the actual linenum to parse_prime() so the error messages include the
- correct line number. OK markus@ some time ago.
+ certificate test.
- OpenBSD-Commit-ID: 4d8e5d3e924d6e8eb70053e3defa23c151a00084
+ OpenBSD-Regress-ID: 388c1e03e1def539d350f139b37d69f12334668d
-commit cce8cbe0ed7d1ba3a575310e0b63c193326ae616
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Sep 15 19:44:06 2018 +1000
+commit ffdde469ed56249f5dc8af98da468dde35531398
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jan 28 00:08:26 2019 +0000
- Fix openssl-1.1 fallout for --without-openssl.
+ upstream: Count the number of key types instead of assuming there
- ok djm@
+ are only two.
+
+ OpenBSD-Regress-ID: 0998702c41235782cf0beee396ec49b5056eaed9
-commit 149519b9f201dac755f3cba4789f4d76fecf0ee1
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 15 19:37:48 2018 +1000
+commit 1d05b4adcba08ab068466e5c08dee2f5417ec53a
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Sat Jan 26 23:42:40 2019 +0100
- add futex(2) syscall to seccomp sandbox
-
- Apparently needed for some glibc/openssl combinations.
+ Cygwin: only tweak sshd_config file if it's new, drop creating sshd user
- Patch from Arkadiusz Miśkiewicz
+ The sshd_config tweaks were executed even if the old file was
+ still in place. Fix that. Also disable sshd user creation.
+ It's not used on Cygwin.
-commit 4488ae1a6940af704c4dbf70f55bf2f756a16536
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 15 19:36:55 2018 +1000
+commit 89843de0c4c733501f6b4f988098e6e06963df37
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Sat Jan 26 23:03:12 2019 +0100
- really add source for authopt_fuzz this time
+ Cygwin: Change service name to cygsshd
+
+ Microsoft hijacked the sshd service name without asking.
-commit 9201784b4a257c8345fbd740bcbdd70054885707
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Sep 15 19:35:40 2018 +1000
+commit 2a9b3a2ce411d16cda9c79ab713c55f65b0ec257
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Jan 27 06:30:53 2019 +0000
- remove accidentally checked-in authopt_fuzz binary
+ upstream: Generate all key supported key types and enable for keyscan
+
+ test.
+
+ OpenBSD-Regress-ID: 72f72ff49946c61bc949e1692dd9e3d71370891b
-commit beb9e522dc7717df08179f9e59f36b361bfa14ab
+commit 391ffc4b9d31fa1f4ad566499fef9176ff8a07dc
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 14 05:26:27 2018 +0000
+Date: Sat Jan 26 22:41:28 2019 +0000
- upstream: second try, deals properly with missing and private-only
+ upstream: check in scp client that filenames sent during
- Use consistent format in debug log for keys readied, offered and
- received during public key authentication.
+ remote->local directory copies satisfy the wildcard specified by the user.
- This makes it a little easier to see what is going on, as each message
- now contains (where available) the key filename, its type and fingerprint,
- and whether the key is hosted in an agent or a token.
+ This checking provides some protection against a malicious server
+ sending unexpected filenames, but it comes at a risk of rejecting wanted
+ files due to differences between client and server wildcard expansion rules.
- OpenBSD-Commit-ID: f1c6a8e9cfc4e108c359db77f24f9a40e1e25ea7
-
-commit 6bc5a24ac867bfdc3ed615589d69ac640f51674b
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Sep 14 15:16:34 2018 +1000
-
- fuzzer harness for authorized_keys option parsing
+ For this reason, this also adds a new -T flag to disable the check.
+
+ reported by Harry Sintonen
+ fix approach suggested by markus@;
+ has been in snaps for ~1wk courtesy deraadt@
+
+ OpenBSD-Commit-ID: 00f44b50d2be8e321973f3c6d014260f8f7a8eda
-commit 6c8b82fc6929b6a9a3f645151b6ec26c5507d9ef
+commit c2c18a39683db382a15b438632afab3f551d50ce
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 14 04:44:04 2018 +0000
+Date: Sat Jan 26 22:35:01 2019 +0000
- upstream: revert following; deals badly with agent keys
+ upstream: make ssh-keyscan return a non-zero exit status if it
- revision 1.285
- date: 2018/09/14 04:17:12; author: djm; state: Exp; lines: +47 -26; commitid: lflGFcNb2X2HebaK;
- Use consistent format in debug log for keys readied, offered and
- received during public key authentication.
+ finds no keys. bz#2903
- This makes it a little easier to see what is going on, as each message
- now contains the key filename, its type and fingerprint, and whether
- the key is hosted in an agent or a token.
+ OpenBSD-Commit-ID: 89f1081fb81d950ebb48e6e73d21807b2723d488
+
+commit 05b9a466700b44d49492edc2aa415fc2e8913dfe
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Jan 24 17:00:29 2019 +0000
+
+ upstream: Accept the host key fingerprint as a synonym for "yes"
- OpenBSD-Commit-ID: e496bd004e452d4b051f33ed9ae6a54ab918f56d
+ when accepting an unknown host key. This allows you to paste a fingerprint
+ obtained out of band into the yes/no prompt and have the client do the
+ comparison for you. ok markus@ djm@
+
+ OpenBSD-Commit-ID: 3c47d10b9f43d3d345e044fd9ec09709583a2767
-commit 6da046f9c3374ce7e269ded15d8ff8bc45017301
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 14 04:17:44 2018 +0000
+commit bdc6c63c80b55bcbaa66b5fde31c1cb1d09a41eb
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Jan 24 16:52:17 2019 +0000
- upstream: garbage-collect moribund ssh_new_private() API.
+ upstream: Have progressmeter force an update at the beginning and
- OpenBSD-Commit-ID: 7c05bf13b094093dfa01848a9306c82eb6e95f6c
+ end of each transfer. Fixes the problem recently introduces where very quick
+ transfers do not display the progressmeter at all. Spotted by naddy@
+
+ OpenBSD-Commit-ID: 68dc46c259e8fdd4f5db3ec2a130f8e4590a7a9a
-commit 1f24ac5fc05252ceb1c1d0e8cab6a283b883c780
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 14 04:17:12 2018 +0000
+commit 258e6ca003e47f944688ad8b8de087b58a7d966c
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Jan 24 02:42:23 2019 +0000
- upstream: Use consistent format in debug log for keys readied,
+ upstream: Check for both EAGAIN and EWOULDBLOCK. This is a no-op
- offered and received during public key authentication.
+ in OpenBSD (they are the same value) but makes things easier in -portable
+ where they may be distinct values. "sigh ok" deraadt@
- This makes it a little easier to see what is going on, as each message
- now contains the key filename, its type and fingerprint, and whether
- the key is hosted in an agent or a token.
+ (ID sync only, portable already had this change).
- OpenBSD-Commit-ID: 2a01d59285a8a7e01185bb0a43316084b4f06a1f
+ OpenBSD-Commit-ID: 91f2bc7c0ecec905915ed59fa37feb9cc90e17d7
-commit 488c9325bb7233e975dbfbf89fa055edc3d3eddc
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Thu Sep 13 15:23:32 2018 +0000
+commit 281ce042579b834cdc1e74314f1fb2eeb75d2612
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Jan 24 02:34:52 2019 +0000
- upstream: Fix warnings caused by user_from_uid() and group_from_gid()
+ upstream: Always initialize 2nd arg to hpdelim2. It populates that
- now returning const char *.
+ *ONLY IF* there's a delimiter. If there's not (the common case) it checked
+ uninitialized memory, which usually passed, but if not would cause spurious
+ failures when the uninitialized memory happens to contain "/". ok deraadt.
- OpenBSD-Commit-ID: b5fe571ea77cfa7b9035062829ab05eb87d7cc6f
+ OpenBSD-Commit-ID: 4291611eaf2a53d4c92f4a57c7f267c9f944e0d3
-commit 0aa1f230846ebce698e52051a107f3127024a05a
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Sep 14 10:31:47 2018 +1000
+commit d05ea255678d9402beda4416cd0360f3e5dfe938
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Jan 23 21:50:56 2019 +0000
- allow SIGUSR1 as synonym for SIGINFO
+ upstream: Remove support for obsolete host/port syntax.
- Lets users on those unfortunate operating systems that lack SIGINFO
- still be able to obtain progress information from unit tests :)
+ host/port was added in 2001 as an alternative to host:port syntax for
+ the benefit of IPv6 users. These days there are establised standards
+ for this like [::1]:22 and the slash syntax is easily mistaken for CIDR
+ notation, which OpenSSH now supports for some things. Remove the slash
+ notation from ListenAddress and PermitOpen. bz#2335, patch from jjelen
+ at redhat.com, ok markus@
+
+ OpenBSD-Commit-ID: fae5f4e23c51a368d6b2d98376069ac2b10ad4b7
-commit d64e78526596f098096113fcf148216798c327ff
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Sep 13 19:05:48 2018 +1000
+commit 177d6c80c557a5e060cd343a0c116a2f1a7f43db
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Jan 23 20:48:52 2019 +0000
- add compat header
+ upstream: Remove duplicate word. bz#2958, patch from jjelen at
+
+ redhat.com
+
+ OpenBSD-Commit-ID: cca3965a8333f2b6aae48b79ec1d72f7a830dd2c
-commit a3fd8074e2e2f06602e25618721f9556c731312c
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 13 09:03:20 2018 +0000
+commit be3e6cba95dffe5fcf190c713525b48c837e7875
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Jan 23 09:49:00 2019 +0000
- upstream: missed a bit of openssl-1.0.x API in this unittest
+ upstream: Remove 3 as a guess for possible generator during moduli
- OpenBSD-Regress-ID: a73a54d7f7381856a3f3a2d25947bee7a9a5dbc9
+ generation. It's not mentioned in RFC4419 and it's not possible for
+ Sophie-Germain primes greater than 5. bz#2330, from Christian Wittenhorst ,
+ ok djm@ tb@
+
+ OpenBSD-Commit-ID: 1467652e6802ad3333b0959282d8d49dfe22c8cd
-commit 86e0a9f3d249d5580390daf58e015e68b01cef10
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 13 05:06:51 2018 +0000
+commit 8976f1c4b2721c26e878151f52bdf346dfe2d54c
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Jan 23 08:01:46 2019 +0000
- upstream: use only openssl-1.1.x API here too
+ upstream: Sanitize scp filenames via snmprintf. To do this we move
- OpenBSD-Regress-ID: ae877064597c349954b1b443769723563cecbc8f
+ the progressmeter formatting outside of signal handler context and have the
+ atomicio callback called for EINTR too. bz#2434 with contributions from djm
+ and jjelen at redhat.com, ok djm@
+
+ OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8
-commit 48f54b9d12c1c79fba333bc86d455d8f4cda8cfc
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Sep 13 12:13:50 2018 +1000
+commit 6249451f381755f792c6b9e2c2f80cdc699c14e2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Jan 24 10:00:20 2019 +1100
- adapt -portable to OpenSSL 1.1x API
+ For broken read/readv comparisons, poll(RW).
- Polyfill missing API with replacement functions extracted from LibreSSL
+ In the cases where we can't compare to read or readv function pointers
+ for some reason we currently ifdef out the poll() used to block while
+ waiting for reads or writes, falling back to busy waiting. This restores
+ the poll() in this case, but has it always check for read or write,
+ removing an inline ifdef in the process.
-commit 86112951d63d48839f035b5795be62635a463f99
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Sep 13 12:12:42 2018 +1000
+commit 5cb503dff4db251520e8bf7d23b9c97c06eee031
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Jan 24 09:55:16 2019 +1100
- forgot to stage these test files in commit d70d061
+ Include unistd.h for strmode().
-commit 482d23bcacdd3664f21cc82a5135f66fc598275f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 13 02:08:33 2018 +0000
+commit f236ca2741f29b5c443c0b2db3aa9afb9ad9befe
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Jan 24 09:50:58 2019 +1100
- upstream: hold our collective noses and use the openssl-1.1.x API in
-
- OpenSSH; feedback and ok tb@ jsing@ markus@
+ Also undef SIMPLEQ_FOREACH_SAFE.
- OpenBSD-Commit-ID: cacbcac87ce5da0d3ca7ef1b38a6f7fb349e4417
+ Prevents macro redefinition warning on at least NetBSD 6.1.
-commit d70d061828730a56636ab6f1f24fe4a8ccefcfc1
+commit be063945e4e7d46b1734d973bf244c350fae172a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:36:45 2018 +0000
+Date: Wed Jan 23 04:51:02 2019 +0000
- upstream: Include certs with multiple RSA signature variants in
+ upstream: allow auto-incrementing certificate serial number for certs
- test data Ensure that cert->signature_key is populated correctly
+ signed in a single commandline.
- OpenBSD-Regress-ID: 56e68f70fe46cb3a193ca207385bdb301fd6603a
+ OpenBSD-Commit-ID: 39881087641efb8cd83c7ec13b9c98280633f45b
-commit f803b2682992cfededd40c91818b653b5d923ef5
+commit 851f80328931975fe68f71af363c4537cb896da2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:23:48 2018 +0000
+Date: Wed Jan 23 04:16:22 2019 +0000
- upstream: test revocation by explicit hash and by fingerprint
+ upstream: move a bunch of global flag variables to main(); make the
- OpenBSD-Regress-ID: 079c18a9ab9663f4af419327c759fc1e2bc78fd8
-
-commit 2de78bc7da70e1338b32feeefcc6045cf49efcd4
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:22:43 2018 +0000
-
- upstream: s/sshkey_demote/sshkey_from_private/g
+ rest static
- OpenBSD-Regress-ID: 782bde7407d94a87aa8d1db7c23750e09d4443c4
+ OpenBSD-Commit-ID: fa431d92584e81fe99f95882f4c56b43fe3242dc
-commit 41c115a5ea1cb79a6a3182773c58a23f760e8076
+commit 2265402dc7d701a9aca9f8a7b7b0fd45b65c479f
Author: Damien Miller <djm@mindrot.org>
-Date: Wed Sep 12 16:50:01 2018 +1000
+Date: Wed Jan 23 13:03:16 2019 +1100
- delete the correct thing; kexfuzz binary
+ depend
-commit f0fcd7e65087db8c2496f13ed39d772f8e38b088
+commit 2c223878e53cc46def760add459f5f7c4fb43e35
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 06:18:59 2018 +0000
+Date: Wed Jan 23 02:01:10 2019 +0000
- upstream: fix edit mistake; spotted by jmc@
+ upstream: switch mainloop from select(2) to poll(2); ok deraadt@
- OpenBSD-Commit-ID: dd724e1c52c9d6084f4cd260ec7e1b2b138261c6
+ OpenBSD-Commit-ID: 37645419a330037d297f6f0adc3b3663e7ae7b2e
-commit 4cc259bac699f4d2a5c52b92230f9e488c88a223
+commit bb956eaa94757ad058ff43631c3a7d6c94d38c2f
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:34:02 2018 +0000
+Date: Wed Jan 23 00:30:41 2019 +0000
- upstream: add SSH_ALLOWED_CA_SIGALGS - the default list of
+ upstream: pass most arguments to the KEX hash functions as sshbuf
- signature algorithms that are allowed for CA signatures. Notably excludes
- ssh-dsa.
-
- ok markus@
+ rather than pointer+length; ok markus@
- OpenBSD-Commit-ID: 1628e4181dc8ab71909378eafe5d06159a22deb4
+ OpenBSD-Commit-ID: ef0c89c52ccc89817a13a5205725148a28492bf7
-commit ba9e788315b1f6a350f910cb2a9e95b2ce584e89
+commit d691588b8e29622c66abf8932362b522cf7f4051
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:32:54 2018 +0000
+Date: Tue Jan 22 22:58:50 2019 +0000
- upstream: add sshkey_check_cert_sigtype() that checks a
+ upstream: backoff reading messages from active connections when the
- cert->signature_type against a supplied whitelist; ok markus
+ input buffer is too full to read one, or if the output buffer is too full to
+ enqueue a response; feedback & ok dtucker@
- OpenBSD-Commit-ID: caadb8073292ed7a9535e5adc067d11d356d9302
+ OpenBSD-Commit-ID: df3c5b6d57c968975875de40d8955cbfed05a6c8
-commit a70fd4ad7bd9f2ed223ff635a3d41e483057f23b
+commit f99ef8de967949a1fc25a5c28263ea32736e5943
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:31:30 2018 +0000
+Date: Tue Jan 22 20:48:01 2019 +0000
- upstream: add cert->signature_type field and keep it in sync with
+ upstream: add -m to usage(); reminded by jmc@
- certificate signature wrt loading and certification operations; ok markus@
+ OpenBSD-Commit-ID: bca476a5236e8f94210290b3e6a507af0434613e
+
+commit 41923ce06ac149453debe472238e0cca7d5a2e5f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jan 22 12:03:58 2019 +0000
+
+ upstream: Correct some bugs in PKCS#11 token PIN handling at
- OpenBSD-Commit-ID: e8b8b9f76b66707a0cd926109c4383db8f664df3
+ initial login, the attempt at reading the PIN could be skipped in some cases
+ especially on devices with integrated PIN readers.
+
+ based on patch from Daniel Kucera in bz#2652; ok markus@
+
+ OpenBSD-Commit-ID: fad70a61c60610afe8bb0db538c90e343e75e58e
-commit 357128ac48630a9970e3af0e6ff820300a28da47
+commit 2162171ad517501ba511fa9f8191945d01857bb4
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:30:10 2018 +0000
+Date: Tue Jan 22 12:00:50 2019 +0000
- upstream: Add "ssh -Q sig" to allow listing supported signature
+ upstream: Support keys that set the CKA_ALWAYS_AUTHENTICATE by
- algorithms ok markus@
+ requring a fresh login after the C_SignInit operation.
- OpenBSD-Commit-ID: 7a8c6eb6c249dc37823ba5081fce64876d10fe2b
+ based on patch from Jakub Jelen in bz#2638; ok markus
+
+ OpenBSD-Commit-ID: a76e66996ba7c0923b46b74d46d499b811786661
-commit 9405c6214f667be604a820c6823b27d0ea77937d
+commit 7a2cb18a215b2cb335da3dc99489c52a91f4925b
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:21:34 2018 +0000
+Date: Tue Jan 22 11:51:25 2019 +0000
- upstream: allow key revocation by SHA256 hash and allow ssh-keygen
+ upstream: Mention that configuration for the destination host is
- to create KRLs using SHA256/base64 key fingerprints; ok markus@
+ not applied to any ProxyJump/-J hosts. This has confused a few people...
- OpenBSD-Commit-ID: a0590fd34e7f1141f2873ab3acc57442560e6a94
+ OpenBSD-Commit-ID: 03f4f641df6ca236c1bfc69836a256b873db868b
-commit 50e2687ee0941c0ea216d6ffea370ffd2c1f14b9
+commit ecd2f33cb772db4fa76776543599f1c1ab6f9fa0
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Sep 12 01:19:12 2018 +0000
+Date: Tue Jan 22 11:40:42 2019 +0000
- upstream: log certificate fingerprint in authentication
+ upstream: Include -m in the synopsis for a few more commands that
- success/failure message (previously we logged only key ID and CA key
- fingerprint).
+ support it
- ok markus@
+ Be more explicit in the description of -m about where it may be used
- OpenBSD-Commit-ID: a8ef2d172b7f1ddbcce26d6434b2de6d94f6c05d
+ Prompted by Jakub Jelen in bz2904
+
+ OpenBSD-Commit-ID: 3b398ac5e05d8a6356710d0ff114536c9d71046c
-commit de37ca909487d23e5844aca289b3f5e75d3f1e1f
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Sep 7 04:26:56 2018 +0000
+commit ff5d2cf4ca373bb4002eef395ed2cbe2ff0826c1
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jan 22 11:26:16 2019 +0000
- upstream: Add FALLTHROUGH comments where appropriate. Patch from
+ upstream: print the full pubkey being attempted at loglevel >=
- jjelen at redhat via bz#2687.
+ debug2; bz2939
- OpenBSD-Commit-ID: c48eb457be697a19d6d2950c6d0879f3ccc851d3
+ OpenBSD-Commit-ID: ac0fe5ca1429ebf4d460bad602adc96de0d7e290
-commit 247766cd3111d5d8c6ea39833a3257ca8fb820f2
+commit 180b520e2bab33b566b4b0cbac7d5f9940935011
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 7 01:42:54 2018 +0000
+Date: Tue Jan 22 11:19:42 2019 +0000
- upstream: ssh -MM requires confirmation for all operations that
-
- change the multiplexing state, not just new sessions.
+ upstream: clarify: ssh-keygen -e only writes public keys, never
- mention that confirmation is checked via ssh-askpass
+ private
- OpenBSD-Commit-ID: 0f1b45551ebb9cc5c9a4fe54ad3b23ce90f1f5c2
+ OpenBSD-Commit-ID: 7de7ff6d274d82febf9feb641e2415ffd6a30bfb
-commit db8bb80e3ac1bcb3e1305d846cd98c6b869bf03f
-Author: mestre@openbsd.org <mestre@openbsd.org>
-Date: Tue Aug 28 12:25:53 2018 +0000
+commit c45616a199c322ca674315de88e788f1d2596e26
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jan 22 11:00:15 2019 +0000
- upstream: fix misplaced parenthesis inside if-clause. it's harmless
-
- and the only issue is showing an unknown error (since it's not defined)
- during fatal(), if it ever an error occurs inside that condition.
+ upstream: mention the new vs. old key formats in the introduction
- OK deraadt@ markus@ djm@
+ and give some hints on how keys may be converted or written in the old
+ format.
- OpenBSD-Commit-ID: acb0a8e6936bfbe590504752d01d1d251a7101d8
+ OpenBSD-Commit-ID: 9c90a9f92eddc249e07fad1204d0e15c8aa13823
-commit 086cc614f550b7d4f100c95e472a6b6b823938ab
-Author: mestre@openbsd.org <mestre@openbsd.org>
-Date: Tue Aug 28 12:17:45 2018 +0000
+commit fd8eb1383a34c986a00ef13d745ae9bd3ea21760
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue Jan 22 06:58:31 2019 +0000
- upstream: fix build with DEBUG_PK enabled
-
- OK dtucker@
+ upstream: tweak previous;
- OpenBSD-Commit-ID: ec1568cf27726e9638a0415481c20c406e7b441c
+ OpenBSD-Commit-ID: d2a80e389da8e7ed71978643d8cbaa8605b597a8
-commit 2678833013e97f8b18f09779b7f70bcbf5eb2ab2
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Sep 7 14:41:53 2018 +1000
+commit 68e924d5473c00057f8532af57741d258c478223
+Author: tb@openbsd.org <tb@openbsd.org>
+Date: Mon Jan 21 23:55:12 2019 +0000
- Handle ngroups>_SC_NGROUPS_MAX.
+ upstream: Forgot to add -J to the synopsis.
- Based on github pull request #99 from Darren Maffat at Oracle: Solaris'
- getgrouplist considers _SC_NGROUPS_MAX more of a guideline and can return
- a larger number of groups. In this case, retry getgrouplist with a
- larger array and defer allocating groups_byname. ok djm@
+ OpenBSD-Commit-ID: 26d95e409a0b72526526fc56ca1caca5cc3d3c5e
-commit 039bf2a81797b8f3af6058d34005a4896a363221
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Sep 7 14:06:57 2018 +1000
+commit 622dedf1a884f2927a9121e672bd9955e12ba108
+Author: tb@openbsd.org <tb@openbsd.org>
+Date: Mon Jan 21 22:50:42 2019 +0000
- Initial len for the fmt=NULL case.
+ upstream: Add a -J option as a shortcut for -o Proxyjump= to scp(1)
- Patch from jjelen at redhat via bz#2687. (OpenSSH never calls
- setproctitle with a null format so len is always initialized).
+ and sftp(1) to match ssh(1)'s interface.
+
+ ok djm
+
+ OpenBSD-Commit-ID: a75bc2d5f329caa7229a7e9fe346c4f41c2663fc
-commit ea9c06e11d2e8fb2f4d5e02f8a41e23d2bd31ca9
+commit c882d74652800150d538e22c80dd2bd3cdd5fae2
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Sep 7 14:01:39 2018 +1000
+Date: Tue Jan 22 20:38:40 2019 +1100
- Include stdlib.h.
-
- Patch from jjelen at redhat via bz#2687.
+ Allow building against OpenSSL dev (3.x) version.
-commit 9617816dbe73ec4d65075f4d897443f63a97c87f
+commit d5520393572eb24aa0e001a1c61f49b104396e45
Author: Damien Miller <djm@mindrot.org>
-Date: Mon Aug 27 13:08:01 2018 +1000
+Date: Tue Jan 22 10:50:40 2019 +1100
- document some more regress control env variables
-
- Specifically SKIP_UNIT, USE_VALGRING and LTESTS. Sort the list of
- environment variables.
-
- Based on patch from Jakub Jelen
+ typo
-commit 71508e06fab14bc415a79a08f5535ad7bffa93d9
+commit 2de9cec54230998ab10161576f77860a2559ccb7
Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 23 15:41:42 2018 +1000
+Date: Tue Jan 22 10:49:52 2019 +1100
- shorten temporary SSH_REGRESS_TMP path
+ add missing header
+
+commit 533cfb01e49a2a30354e191669dc3159e03e99a7
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 22:18:24 2019 +0000
+
+ upstream: switch sntrup implementation source from supercop to
- Previous path was exceeding max socket length on at least one platform (OSX)
+ libpqcrypto; the latter is almost identical but doesn't rely on signed
+ underflow to implement an optimised integer sort; from markus@
+
+ OpenBSD-Commit-ID: cd09bbf0e0fcef1bedca69fdf7990dc360567cf8
-commit 26739cf5bdc9030a583b41ae5261dedd862060f0
+commit d50ab3cd6fb859888a26b4d4e333239b4f6bf573
Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 23 13:06:02 2018 +1000
+Date: Tue Jan 22 00:02:23 2019 +1100
- rebuild dependencies
+ new files need includes.h
-commit ff729025c7463cf5d0a8d1ca1823306e48c6d4cf
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Aug 23 13:03:32 2018 +1000
+commit c7670b091a7174760d619ef6738b4f26b2093301
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 12:53:35 2019 +0000
- fix path in distclean target
+ upstream: add "-v" flags to ssh-add and ssh-pkcs11-helper to turn up
- Patch from Jakub Jelen
+ debug verbosity.
+
+ Make ssh-agent turn on ssh-pkcs11-helper's verbosity when it is run
+ in debug mode ("ssh-agent -d"), so we get to see errors from the
+ PKCS#11 code.
+
+ ok markus@
+
+ OpenBSD-Commit-ID: 0a798643c6a92a508df6bd121253ba1c8bee659d
-commit 7fef173c28f7462dcd8ee017fdf12b5073f54c02
+commit 49d8c8e214d39acf752903566b105d06c565442a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Aug 23 03:01:08 2018 +0000
+Date: Mon Jan 21 12:50:12 2019 +0000
- upstream: memleak introduced in r1.83; from Colin Watson
+ upstream: adapt to changes in KEX APIs and file removals
- OpenBSD-Commit-ID: 5c019104c280cbd549a264a7217b67665e5732dc
+ OpenBSD-Regress-ID: 54d6857e7c58999c7a6d40942ab0fed3529f43ca
-commit b8ae02a2896778b8984c7f51566c7f0f56fa8b56
-Author: schwarze@openbsd.org <schwarze@openbsd.org>
-Date: Tue Aug 21 13:56:27 2018 +0000
+commit 35ecc53a83f8e8baab2e37549addfd05c73c30f1
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 12:35:20 2019 +0000
- upstream: AIX reports the CODESET as "ISO8859-1" in the POSIX locale.
-
- Treating that as a safe encoding is OK because even when other systems return
- that string for real ISO8859-1, it is still safe in the sense that it is
- ASCII-compatible and stateless.
-
- Issue reported by Val dot Baranov at duke dot edu. Additional
- information provided by Michael dot Felt at felt dot demon dot nl.
- Tested by Michael Felt on AIX 6.1 and by Val Baranov on AIX 7.1.
- Tweak and OK djm@.
+ upstream: adapt to changes in KEX API and file removals
- OpenBSD-Commit-ID: 36f1210e0b229817d10eb490d6038f507b8256a7
+ OpenBSD-Regress-ID: 92cad022d3b0d11e08f3e0055d6a14b8f994c0d7
-commit bc44ee088ad269d232e514f037c87ada4c2fd3f0
-Author: Tim Rice <tim@multitalents.net>
-Date: Tue Aug 21 08:57:24 2018 -0700
+commit 7d69aae64c35868cc4f644583ab973113a79480e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 12:29:35 2019 +0000
- modified: openbsd-compat/port-uw.c
- remove obsolete and un-needed include
+ upstream: adapt to bignum1 API removal and bignum2 API change
+
+ OpenBSD-Regress-ID: cea6ff270f3d560de86b355a87a2c95b55a5ca63
-commit 829fc28a9c54e3f812ee7248c7a3e31eeb4f0b3a
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Aug 20 15:57:29 2018 +1000
+commit beab553f0a9578ef9bffe28b2c779725e77b39ec
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 09:13:41 2019 +0000
- Missing unistd.h for regress/mkdtemp.c
+ upstream: remove hack to use non-system libcrypto
+
+ OpenBSD-Regress-ID: ce72487327eee4dfae1ab0212a1f33871fe0809f
-commit c8313e492355a368a91799131520d92743d8d16c
+commit 4dc06bd57996f1a46b4c3bababe0d09bc89098f7
Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 17 05:45:20 2018 +1000
+Date: Mon Jan 21 23:14:04 2019 +1100
- update version numbers in anticipation of release
+ depend
-commit 477b49a34b89f506f4794b35e3c70b3e2e83cd38
-Author: Corinna Vinschen <vinschen@redhat.com>
-Date: Mon Aug 13 17:08:51 2018 +0200
+commit 70edd73edc4df54e5eee50cd27c25427b34612f8
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 12:08:13 2019 +0000
- configure: work around GCC shortcoming on Cygwin
-
- Cygwin's latest 7.x GCC allows to specify -mfunction-return=thunk
- as well as -mindirect-branch=thunk on the command line, albeit
- producing invalid code, leading to an error at link stage.
-
- The check in configure.ac only checks if the option is present,
- but not if it produces valid code.
+ upstream: fix reversed arguments to kex_load_hostkey(); manifested as
- This patch fixes it by special-casing Cygwin. Another solution
- may be to change these to linker checks.
+ errors in cert-hostkey.sh regress failures.
- Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
+ OpenBSD-Commit-ID: 12dab63850b844f84d5a67e86d9e21a42fba93ba
-commit b0917945efa374be7648d67dbbaaff323ab39edc
-Author: Corinna Vinschen <vinschen@redhat.com>
-Date: Mon Aug 13 17:05:05 2018 +0200
+commit f1185abbf0c9108e639297addc77f8757ee00eb3
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 11:22:00 2019 +0000
- cygwin: add missing stdarg.h include
+ upstream: forgot to cvs add this file in previous series of commits;
- Further header file standarization in Cygwin uncovered a lazy
- indirect include in bsd-cygwin_util.c
+ grrr
- Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
+ OpenBSD-Commit-ID: bcff316c3e7da8fd15333e05d244442c3aaa66b0
-commit c3903c38b0fd168ab3d925c2b129d1a599593426
+commit 7bef390b625bdc080f0fd4499ef03cef60fca4fa
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Aug 13 02:41:05 2018 +0000
+Date: Mon Jan 21 10:44:21 2019 +0000
- upstream: revert compat.[ch] section of the following change. It
+ upstream: nothing shall escape this purge
- causes double-free under some circumstances.
+ OpenBSD-Commit-ID: 4795b0ff142b45448f7e15f3c2f77a947191b217
+
+commit aaca72d6f1279b842066e07bff797019efeb2c23
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 10:40:11 2019 +0000
+
+ upstream: rename kex->kem_client_pub -> kex->client_pub now that
- --
+ KEM has been renamed to kexgen
- date: 2018/07/31 03:07:24; author: djm; state: Exp; lines: +33 -18; commitid: f7g4UI8eeOXReTPh;
- fix some memory leaks spotted by Coverity via Jakub Jelen in bz#2366
- feedback and ok dtucker@
+ from markus@ ok djm@
- OpenBSD-Commit-ID: 1e77547f60fdb5e2ffe23e2e4733c54d8d2d1137
+ OpenBSD-Commit-ID: fac6da5dc63530ad0da537db022a9a4cfbe8bed8
-commit 1b9dd4aa15208100fbc3650f33ea052255578282
+commit 70867e1ca2eb08bbd494fe9c568df4fd3b35b867
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Aug 12 20:19:13 2018 +0000
+Date: Mon Jan 21 10:38:54 2019 +0000
- upstream: better diagnosics on alg list assembly errors; ok
+ upstream: merge kexkem[cs] into kexgen
- deraadt@ markus@
+ from markus@ ok djm@
- OpenBSD-Commit-ID: 5a557e74b839daf13cc105924d2af06a1560faee
+ OpenBSD-Commit-ID: 87d886b7f1812ff9355fda1435f6ea9b71a0ac89
-commit e36a5f61b0f5bebf6d49c215d228cd99dfe86e28
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Aug 11 18:08:45 2018 -0700
+commit 71e67fff946396caa110a7964da23480757258ff
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 10:35:09 2019 +0000
- Some AIX fixes; report from Michael Felt
+ upstream: pass values used in KEX hash computation as sshbuf
+
+ rather than pointer+len
+
+ suggested by me; implemented by markus@ ok me
+
+ OpenBSD-Commit-ID: 994f33c464f4a9e0f1d21909fa3e379f5a0910f0
-commit 2f4766ceefe6657c5ad5fe92d13c411872acae0e
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Aug 10 01:35:49 2018 +0000
+commit 4b83e2a2cc0c12e671a77eaba1c1245894f4e884
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 10:33:49 2019 +0000
- upstream: The script that cooks up PuTTY format host keys does not
+ upstream: remove kex_derive_keys_bn wrapper; no unused since the
- understand the new key format so convert back to old format to create the
- PuTTY key and remove it once done.
+ DH-like KEX methods have moved to KEM
- OpenBSD-Regress-ID: 2a449a18846c3a144bc645135b551ba6177e38d3
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: bde9809103832f349545e4f5bb733d316db9a060
-commit e1b26ce504662a5d5b991091228984ccfd25f280
+commit 92dda34e373832f34a1944e5d9ebbebb184dedc1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 10 00:44:01 2018 +0000
+Date: Mon Jan 21 10:29:56 2019 +0000
- upstream: improve
+ upstream: use KEM API for vanilla ECDH
- OpenBSD-Commit-ID: 40d839db0977b4e7ac8b647b16d5411d4faf2f60
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 6fbff96339a929835536b5730585d1d6057a352c
-commit 7c712966a3139622f7fb55045368d05de4e6782c
+commit b72357217cbe510a3ae155307a7be6b9181f1d1b
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Jan 21 23:11:21 2019 +1100
+
+ fixup missing ssherr.h
+
+commit 9c9c97e14fe190931f341876ad98213e1e1dc19f
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 10 00:42:29 2018 +0000
+Date: Mon Jan 21 10:28:01 2019 +0000
- upstream: Describe pubkey format, prompted by bz#2853
+ upstream: use KEM API for vanilla DH KEX
- While I'm here, describe and link to the remaining local PROTOCOL.*
- docs that weren't already mentioned (PROTOCOL.key, PROTOCOL.krl and
- PROTOCOL.mux)
+ from markus@ ok djm@
- OpenBSD-Commit-ID: 2a900f9b994ba4d53e7aeb467d44d75829fd1231
+ OpenBSD-Commit-ID: af56466426b08a8be275412ae2743319e3d277c9
-commit ef100a2c5a8ed83afac0b8f36520815803da227a
+commit 2f6a9ddbbf6ca8623c53c323ff17fb6d68d66970
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 10 00:27:15 2018 +0000
+Date: Mon Jan 21 10:24:09 2019 +0000
- upstream: fix numbering
+ upstream: use KEM API for vanilla c25519 KEX
- OpenBSD-Commit-ID: bc7a1764dff23fa4c5ff0e3379c9c4d5b63c9596
+ OpenBSD-Commit-ID: 38d937b85ff770886379dd66a8f32ab0c1c35c1f
-commit ed7bd5d93fe14c7bd90febd29b858ea985d14d45
+commit dfd591618cdf2c96727ac0eb65f89cf54af0d97e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Aug 8 01:16:01 2018 +0000
+Date: Mon Jan 21 10:20:12 2019 +0000
- upstream: Use new private key format by default. This format is
+ upstream: Add support for a PQC KEX/KEM:
- suported by OpenSSH >= 6.5 (released January 2014), so it should be supported
- by most OpenSSH versions in active use.
+ sntrup4591761x25519-sha512@tinyssh.org using the Streamlined NTRU Prime
+ 4591^761 implementation from SUPERCOP coupled with X25519 as a stop-loss. Not
+ enabled by default.
- It is possible to convert new-format private keys to the older
- format using "ssh-keygen -f /path/key -pm PEM".
+ introduce KEM API; a simplified framework for DH-ish KEX methods.
- ok deraadt dtucker
+ from markus@ feedback & ok djm@
- OpenBSD-Commit-ID: e3bd4f2509a2103bfa2f710733426af3ad6d8ab8
+ OpenBSD-Commit-ID: d687f76cffd3561dd73eb302d17a1c3bf321d1a7
-commit 967226a1bdde59ea137e8f0df871854ff7b91366
+commit b1b2ff4ed559051d1035419f8f236275fa66d5d6
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Aug 4 00:55:06 2018 +0000
+Date: Mon Jan 21 10:07:22 2019 +0000
- upstream: invalidate dh->priv_key after freeing it in error path;
+ upstream: factor out kex_verify_hostkey() - again, duplicated
- avoids unlikely double-free later. Reported by Viktor Dukhovni via
- https://github.com/openssh/openssh-portable/pull/96 feedback jsing@ tb@
+ almost exactly across client and server for several KEX methods.
- OpenBSD-Commit-ID: e317eb17c3e05500ae851f279ef6486f0457c805
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 4e4a16d949dadde002a0aacf6d280a684e20829c
-commit 74287f5df9966a0648b4a68417451dd18f079ab8
+commit bb39bafb6dc520cc097780f4611a52da7f19c3e2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 31 03:10:27 2018 +0000
+Date: Mon Jan 21 10:05:09 2019 +0000
- upstream: delay bailout for invalid authentic
+ upstream: factor out kex_load_hostkey() - this is duplicated in
- =?UTF-8?q?ating=20user=20until=20after=20the=20packet=20containing=20the?=
- =?UTF-8?q?=20request=20has=20been=20fully=20parsed.=20Reported=20by=20Dar?=
- =?UTF-8?q?iusz=20Tytko=20and=20Micha=C5=82=20Sajdak;=20ok=20deraadt?=
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
+ both the client and server implementations for most KEX methods.
- OpenBSD-Commit-ID: b4891882fbe413f230fe8ac8a37349b03bd0b70d
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 8232fa7c21fbfbcaf838313b0c166dc6c8762f3c
-commit 1a66079c0669813306cc69e5776a4acd9fb49015
+commit dec5e9d33891e3bc3f1395d7db0e56fdc7f86dfc
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 31 03:07:24 2018 +0000
+Date: Mon Jan 21 10:03:37 2019 +0000
- upstream: fix some memory leaks spotted by Coverity via Jakub Jelen
+ upstream: factor out kex_dh_compute_key() - it's shared between
- in bz#2366 feedback and ok dtucker@
+ plain DH KEX and DH GEX in both the client and server implementations
- OpenBSD-Commit-ID: 8402bbae67d578bedbadb0ce68ff7c5a136ef563
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 12186e18791fffcd4642c82e7e0cfdd7ea37e2ec
-commit 87f08be054b7eeadbb9cdeb3fb4872be79ccf218
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 20 13:18:28 2018 +1000
+commit e93bd98eab79b9a78f64ee8dd4dffc4d3979c7ae
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 10:00:23 2019 +0000
- Remove support for S/Key
+ upstream: factor out DH keygen; it's identical between the client
- Most people will 1) be using modern multi-factor authentication methods
- like TOTP/OATH etc and 2) be getting support for multi-factor
- authentication via PAM or BSD Auth.
+ and the server
+
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 2be57f6a0d44f1ab2c8de2b1b5d6f530c387fae9
-commit 5d14019ba2ff54acbfd20a6b9b96bb860a8c7c31
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Fri Jul 27 12:03:17 2018 +0000
+commit 5ae3f6d314465026d028af82609c1d49ad197655
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 09:55:52 2019 +0000
- upstream: avoid expensive channel_open_message() calls; ok djm@
+ upstream: save the derived session id in kex_derive_keys() rather
- OpenBSD-Commit-ID: aea3b5512ad681cd8710367d743e8a753d4425d9
+ than making each kex method implementation do it.
+
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: d61ade9c8d1e13f665f8663c552abff8c8a30673
-commit e655ee04a3cb7999dbf9641b25192353e2b69418
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jul 27 05:34:42 2018 +0000
+commit 7be8572b32a15d5c3dba897f252e2e04e991c307
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 09:54:11 2019 +0000
- upstream: Now that ssh can't be setuid, remove the
+ upstream: Make sshpkt_get_bignum2() allocate the bignum it is
- original_real_uid and original_effective_uid globals and replace with calls
- to plain getuid(). ok djm@
+ parsing rather than make the caller do it. Saves a lot of boilerplate code.
- OpenBSD-Commit-ID: 92561c0cd418d34e6841e20ba09160583e27b68c
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 576bf784f9a240f5a1401f7005364e59aed3bce9
-commit 73ddb25bae4c33a0db361ac13f2e3a60d7c6c4a5
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jul 27 05:13:02 2018 +0000
+commit 803178bd5da7e72be94ba5b4c4c196d4b542da4d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 09:52:25 2019 +0000
- upstream: Remove uid checks from low port binds. Now that ssh
+ upstream: remove obsolete (SSH v.1) sshbuf_get/put_bignum1
- cannot be setuid and sshd always has privsep on, we can remove the uid checks
- for low port binds and just let the system do the check. We leave a sanity
- check for the !privsep case so long as the code is stil there. with & ok
- djm@
+ functions
- OpenBSD-Commit-ID: 9535cfdbd1cd54486fdbedfaee44ce4367ec7ca0
+ from markus@ ok djm@
+
+ OpenBSD-Commit-ID: 0380b1b2d9de063de3c5a097481a622e6a04943e
-commit c12033e102760d043bc5c98e6c8180e4d331b0df
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jul 27 03:55:22 2018 +0000
+commit f3ebaffd8714be31d4345f90af64992de4b3bba2
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 09:49:37 2019 +0000
- upstream: ssh(1) no longer supports being setuid root. Remove reference
+ upstream: fix all-zero check in kexc25519_shared_key
- to crc32 which went with protocol 1. Pointed out by deraadt@.
+ from markus@ ok djm@
- OpenBSD-Commit-ID: f8763c25fd96ed91dd1abdab5667fd2e27e377b6
+ OpenBSD-Commit-ID: 60b1d364e0d9d34d1d1ef1620cb92e36cf06712d
-commit 4492e2ec4e1956a277ef507f51d66e5c2aafaaf8
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 27 14:15:28 2018 +1000
+commit 9d1a9771d0ad3a83af733bf3d2650b53f43c269f
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Mon Jan 21 07:09:10 2019 +0000
- correct snprintf truncation check in closefrom()
+ upstream: - -T was added to the first synopsis by mistake - since
- Truncation cannot happen unless the system has set PATH_MAX to some
- nonsensically low value.
+ "..." denotes optional, no need to surround it in []
- bz#2862, patch from Daniel Le
+ ok djm
+
+ OpenBSD-Commit-ID: 918f6d8eed4e0d8d9ef5eadae1b8983d796f0e25
-commit 149cab325a8599a003364ed833f878449c15f259
+commit 2f0bad2bf85391dbb41315ab55032ec522660617
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jul 27 13:46:06 2018 +1000
+Date: Mon Jan 21 21:28:27 2019 +1100
- Include stdarg.h in mkdtemp for va_list.
+ Make --with-rpath take a flag instead of yes/no.
+
+ Linkers need various flags for -rpath and similar, so make --with-rpath
+ take an optional flag argument which is passed to the linker. ok djm@
-commit 6728f31bdfdc864d192773c32465b1860e23f556
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed Jul 25 17:12:35 2018 +0000
+commit 23490a6c970ea1d03581a3b4208f2eb7a675f453
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Jan 21 15:05:43 2019 +1100
- upstream: Don't redefine Makefile choices which come correct from
+ fix previous test
+
+commit b6dd3277f2c49f9584a2097bc792e8f480397e87
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Jan 21 13:50:17 2019 +1100
+
+ Wrap ECC static globals in EC_KEY_METHOD_NEW too.
+
+commit b2eb9db35b7191613f2f4b934d57b25938bb34b3
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Jan 21 12:53:40 2019 +1100
+
+ pass TEST_SSH_SSHPKCS11HELPER to regress tests
+
+commit ba58a529f45b3dae2db68607d8c54ae96e90e705
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Jan 21 12:31:29 2019 +1100
+
+ make agent-pkcs11 search harder for softhsm2.so
+
+commit 662be40c62339ab645113c930ce689466f028938
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 02:05:38 2019 +0000
+
+ upstream: always print the caller's error message in ossl_error(),
- bsd.*.mk ok markus
+ even when there are no libcrypto errors to report.
- OpenBSD-Commit-ID: 814b2f670df75759e1581ecef530980b2b3d7e0f
+ OpenBSD-Commit-ID: 09ebaa8f706e0eccedd209775baa1eee2ada806a
-commit 21fd477a855753c1a8e450963669e28e39c3b5d2
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed Jul 25 13:56:23 2018 +0000
+commit ce46c3a077dfb4c531ccffcfff03f37775725b75
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 02:01:03 2019 +0000
- upstream: fix indent; Clemens Goessnitzer
+ upstream: get the ex_data (pkcs11_key object) back from the keys at
- OpenBSD-Commit-ID: b5149a6d92b264d35f879d24608087b254857a83
+ the index at which it was inserted, rather than assuming index 0
+
+ OpenBSD-Commit-ID: 1f3a6ce0346c8014e895e50423bef16401510aa8
-commit 8e433c2083db8664c41499ee146448ea7ebe7dbf
-Author: beck@openbsd.org <beck@openbsd.org>
-Date: Wed Jul 25 13:10:56 2018 +0000
+commit 0a5f2ea35626022299ece3c8817a1abe8cf37b3e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jan 21 01:05:00 2019 +0000
- upstream: Use the caller provided (copied) pwent struct in
-
- load_public_identity_files instead of calling getpwuid() again and discarding
- the argument. This prevents a client crash where tilde_expand_filename calls
- getpwuid() again before the pwent pointer is used. Issue noticed and reported
- by Pierre-Olivier Martel <pom@apple.com> ok djm@ deraadt@
+ upstream: GSSAPI code got missed when converting to new packet API
- OpenBSD-Commit-ID: a067d74b5b098763736c94cc1368de8ea3f0b157
+ OpenBSD-Commit-ID: 37e4f06ab4a0f4214430ff462ba91acba28b7851
-commit e2127abb105ae72b6fda64fff150e6b24b3f1317
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Jul 23 19:53:55 2018 +0000
+commit 2efcf812b4c1555ca3aff744820a3b3bccd68298
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Jan 21 11:57:21 2019 +1100
- upstream: oops, failed to notice that SEE ALSO got messed up;
+ Fix -Wunused when compiling PKCS#11 without ECDSA
+
+commit 3c0c657ed7cd335fc05c0852d88232ca7e92a5d9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:26:44 2019 +0000
+
+ upstream: allow override of ssh-pkcs11-helper binary via
- OpenBSD-Commit-ID: 61c1306542cefdc6e59ac331751afe961557427d
+ $TEST_SSH_SSHPKCS11HELPER from markus@
+
+ OpenBSD-Regress-ID: 7382a3d76746f5a792d106912a5819fd5e49e469
-commit ddf1b797c2d26bbbc9d410aa4f484cbe94673587
-Author: kn@openbsd.org <kn@openbsd.org>
-Date: Mon Jul 23 19:02:49 2018 +0000
+commit 760ae37b4505453c6fa4faf1aa39a8671ab053af
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:25:25 2019 +0000
- upstream: Point to glob in section 7 for the actual list of special
+ upstream: adapt agent-pkcs11.sh test to softhsm2 and add support
- characters instead the C API in section 3.
+ for ECDSA keys
- OK millert jmc nicm, "the right idea" deraadt
+ work by markus@, ok djm@
- OpenBSD-Commit-ID: a74fd215488c382809e4d041613aeba4a4b1ffc6
+ OpenBSD-Regress-ID: 1ebc2be0e88eff1b6d8be2f9c00cdc60723509fe
-commit 01c98d9661d0ed6156e8602b650f72eed9fc4d12
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Jul 22 12:16:59 2018 +0000
+commit b2ce8b31a1f974a13e6d12e0a0c132b50bc45115
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:24:19 2019 +0000
- upstream: Switch authorized_keys example from ssh-dss to ssh-rsa
+ upstream: add "extra:" target to run some extra tests that are not
- since the former is no longer enabled by default. Pointed out by Daniel A.
- Maierhofer, ok jmc
+ enabled by default (currently includes agent-pkcs11.sh); from markus@
- OpenBSD-Commit-ID: 6a196cef53d7524e0c9b58cdbc1b5609debaf8c7
+ OpenBSD-Regress-ID: 9a969e1adcd117fea174d368dcb9c61eb50a2a3c
-commit 472269f8fe19343971c2d08f504ab5cbb8234b33
+commit 632976418d60b7193597bbc6ac7ca33981a41aab
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jul 20 05:01:10 2018 +0000
+Date: Mon Jan 21 00:47:34 2019 +0000
- upstream: slightly-clearer description for AuthenticationMethods - the
+ upstream: use ECDSA_SIG_set0() instead of poking signature values into
- lists have comma-separated elements; bz#2663 from Hans Meier
+ structure directly; the latter works on LibreSSL but not on OpenSSL. From
+ portable.
- OpenBSD-Commit-ID: 931c983d0fde4764d0942fb2c2b5017635993b5a
+ OpenBSD-Commit-ID: 5b22a1919d9cee907d3f8a029167f70a481891c6
-commit c59aca8adbdf7f5597084ad360a19bedb3f80970
+commit 5de6ac2bad11175135d9b819b3546db0ca0b4878
Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 20 14:53:42 2018 +1000
+Date: Mon Jan 21 11:44:19 2019 +1100
- Create control sockets in clean temp directories
+ remove HAVE_DLOPEN that snuck in
- Adds a regress/mkdtemp tool and uses it to create empty temp
- directories for tests needing control sockets.
+ portable doesn't use this
+
+commit e2cb445d786f7572da2af93e3433308eaed1093a
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Jan 21 11:32:28 2019 +1100
+
+ conditionalise ECDSA PKCS#11 support
- Patch from Colin Watson via bz#2660; ok dtucker
+ Require EC_KEY_METHOD support in libcrypto, evidenced by presence
+ of EC_KEY_METHOD_new() function.
-commit 6ad8648e83e4f4ace37b742a05c2a6b6b872514e
+commit fcb1b0937182d0137a3c357c89735d0dc5869d54
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jul 20 03:46:34 2018 +0000
+Date: Sun Jan 20 23:12:35 2019 +0000
- upstream: remove unused zlib.h
+ upstream: we use singleton pkcs#11 RSA_METHOD and EC_KEY_METHOD
- OpenBSD-Commit-ID: 8d274a9b467c7958df12668b49144056819f79f1
+ now, so there is no need to keep a copy of each in the pkcs11_key object.
+
+ work by markus@, ok djm@
+
+ OpenBSD-Commit-ID: 43b4856516e45c0595f17a8e95b2daee05f12faa
-commit 3ba6e6883527fe517b6e4a824876e2fe62af22fc
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Jul 19 23:03:16 2018 +0000
+commit 6529409e85890cd6df7e5e81d04e393b1d2e4b0b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:11:11 2019 +0000
- upstream: Fix typo in comment. From Alexandru Iacob via github.
+ upstream: KNF previous; from markus@
- OpenBSD-Commit-ID: eff4ec07c6c8c5483533da43a4dda37d72ef7f1d
+ OpenBSD-Commit-ID: 3dfe35e25b310c3968b1e4e53a0cb1d03bda5395
-commit c77bc73c91bc656e343a1961756e09dd1b170820
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jul 20 13:48:51 2018 +1000
+commit 58622a8c82f4e2aad630580543f51ba537c1f39e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:10:33 2019 +0000
- Explicitly include openssl before zlib.
+ upstream: use OpenSSL's RSA reference counting hooks to
- Some versions of OpenSSL have "free_func" in their headers, which zlib
- typedefs. Including openssl after zlib (eg via sshkey.h) results in
- "syntax error before `free_func'", which this fixes.
+ implicitly clean up pkcs11_key objects when their owning RSA object's
+ reference count drops to zero. Simplifies the cleanup path and makes it more
+ like ECDSA's
+
+ work by markus@, ok djm@
+
+ OpenBSD-Commit-ID: 74b9c98f405cd78f7148e9e4a4982336cd3df25c
-commit 95d41e90eafcd1286a901e8e361e4a37b98aeb52
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Jul 19 10:28:47 2018 +0000
+commit f118542fc82a3b3ab0360955b33bc5a271ea709f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:08:24 2019 +0000
- upstream: Deprecate UsePrivilegedPort now that support for running
-
- ssh(1) setuid has been removed, remove supporting code and clean up
- references to it in the man pages
+ upstream: make the PKCS#11 RSA code more like the new PKCS#11
- We have not shipped ssh(1) the setuid bit since 2002. If ayone
- really needs to make connections from a low port number this can
- be implemented via a small setuid ProxyCommand.
+ ECDSA code: use a single custom RSA_METHOD instead of a method per key
- ok markus@ jmc@ djm@
+ suggested by me, but markus@ did all the work.
+ ok djm@
- OpenBSD-Commit-ID: d03364610b7123ae4c6792f5274bd147b6de717e
+ OpenBSD-Commit-ID: 8aafcebe923dc742fc5537a995cee549d07e4b2e
-commit 258dc8bb07dfb35a46e52b0822a2c5b7027df60a
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Jul 18 11:34:04 2018 +0000
+commit 445cfce49dfc904c6b8ab25afa2f43130296c1a5
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:05:52 2019 +0000
- upstream: Remove support for running ssh(1) setuid and fatal if
+ upstream: fix leak of ECDSA pkcs11_key objects
- attempted. Do not link uidwap.c into ssh any more. Neuters
- UsePrivilegedPort, which will be marked as deprecated shortly. ok markus@
- djm@
+ work by markus, ok djm@
- OpenBSD-Commit-ID: c4ba5bf9c096f57a6ed15b713a1d7e9e2e373c42
+ OpenBSD-Commit-ID: 9fc0c4f1d640aaa5f19b8d70f37ea19b8ad284a1
-commit ac590760b251506b0a152551abbf8e8d6dc2f527
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Jul 16 22:25:01 2018 +0000
+commit 8a2467583f0b5760787273796ec929190c3f16ee
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:03:26 2019 +0000
- upstream: Slot 0 in the hostbased key array was previously RSA1,
+ upstream: use EVP_PKEY_get0_EC_KEY() instead of direct access of
- but that is now gone and the slot is unused so remove it. Remove two
- now-unused macros, and add an array bounds check to the two remaining ones
- (array is statically sized, so mostly a safety check on future changes). ok
- markus@
+ EC_KEY internals as that won't work on OpenSSL
- OpenBSD-Commit-ID: 2e4c0ca6cc1d8daeccead2aa56192a3f9d5e1e7a
+ work by markus@, feedback and ok djm@
+
+ OpenBSD-Commit-ID: 4a99cdb89fbd6f5155ef8c521c99dc66e2612700
-commit 26efc2f5df0e3bcf6a6bbdd0506fd682d60c2145
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Jul 16 11:05:41 2018 +0000
+commit 24757c1ae309324e98d50e5935478655be04e549
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 23:01:59 2019 +0000
- upstream: Remove support for loading HostBasedAuthentication keys
+ upstream: cleanup PKCS#11 ECDSA pubkey loading: the returned
- directly in ssh(1) and always use ssh-keysign. This removes one of the few
- remaining reasons why ssh(1) might be setuid. ok markus@
+ object should never have a DER header
- OpenBSD-Commit-ID: 97f01e1448707129a20d75f86bad5d27c3cf0b7d
+ work by markus; feedback and ok djm@
+
+ OpenBSD-Commit-ID: b617fa585eddbbf0b1245b58b7a3c4b8d613db17
-commit 3eb7f1038d17af7aea3c2c62d1e30cd545607640
+commit 749aef30321595435ddacef2f31d7a8f2b289309
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jul 16 07:06:50 2018 +0000
+Date: Sun Jan 20 23:00:12 2019 +0000
- upstream: keep options.identity_file_userprovided array in sync when we
+ upstream: cleanup unnecessary code in ECDSA pkcs#11 signature
- load keys, fixing some spurious error messages; ok markus
+ work by markus@, feedback and ok djm@
- OpenBSD-Commit-ID: c63e3d5200ee2cf9e35bda98de847302566c6a00
+ OpenBSD-Commit-ID: affa5ca7d58d59fbd16169f77771dcdbd2b0306d
-commit 2f131e1b34502aa19f345e89cabf6fa3fc097f09
+commit 0c50992af49b562970dd0ba3f8f151f1119e260e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jul 16 03:09:59 2018 +0000
+Date: Sun Jan 20 22:57:45 2019 +0000
- upstream: memleak in unittest; found by valgrind
+ upstream: cleanup pkcs#11 client code: use sshkey_new in instead
- OpenBSD-Regress-ID: 168c23b0fb09fc3d0b438628990d3fd9260a8a5e
+ of stack- allocating a sshkey
+
+ work by markus@, ok djm@
+
+ OpenBSD-Commit-ID: a048eb6ec8aa7fa97330af927022c0da77521f91
-commit de2997a4cf22ca0a524f0e5b451693c583e2fd89
+commit 854bd8674ee5074a239f7cadf757d55454802e41
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jul 16 03:09:13 2018 +0000
+Date: Sun Jan 20 22:54:30 2019 +0000
- upstream: memleaks; found by valgrind
+ upstream: allow override of the pkcs#11 helper binary via
- OpenBSD-Commit-ID: 6c3ba22be53e753c899545f771e8399fc93cd844
-
-commit 61cc0003eb37fa07603c969c12b7c795caa498f3
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Jul 14 16:49:01 2018 +1000
-
- Undef a few new macros in sys-queue.h.
+ $SSH_PKCS11_HELPER; needed for regress tests.
- Prevents macro redefinition warnings on OSX.
-
-commit 30a2c213877a54a44dfdffb6ca8db70be5b457e0
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jul 13 13:40:20 2018 +1000
-
- Include unistd.h for geteuid declaration.
+ work by markus@, ok me
+
+ OpenBSD-Commit-ID: f78d8185500bd7c37aeaf7bd27336db62f0f7a83
-commit 1dd32c23f2a85714dfafe2a9cc516971d187caa4
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jul 13 13:38:10 2018 +1000
+commit 93f02107f44d63a016d8c23ebd2ca9205c495c48
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jan 20 22:51:37 2019 +0000
- Fallout from buffer conversion in AUDIT_EVENTS.
+ upstream: add support for ECDSA keys in PKCS#11 tokens
- Supply missing "int r" and fix error path for sshbuf_new().
+ Work by markus@ and Pedro Martelletto, feedback and ok me@
+
+ OpenBSD-Commit-ID: a37d651e221341376636056512bddfc16efb4424
-commit 7449c178e943e5c4f6c8416a4e41d93b70c11c9e
+commit aa22c20e0c36c2fc610cfcc793b0d14079c38814
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jul 13 02:13:50 2018 +0000
+Date: Sun Jan 20 22:03:29 2019 +0000
- upstream: make this use ssh_proxy rather than starting/stopping a
+ upstream: add option to test whether keys in an agent are usable,
- daemon for each testcase
+ by performing a signature and a verification using each key "ssh-add -T
+ pubkey [...]"
- OpenBSD-Regress-ID: 608b7655ea65b1ba8fff5a13ce9caa60ef0c8166
+ work by markus@, ok djm@
+
+ OpenBSD-Commit-ID: 931b888a600b6a883f65375bd5f73a4776c6d19b
-commit dbab02f9208d9baa134cec1d007054ec82b96ca9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jul 13 02:13:19 2018 +0000
+commit a36b0b14a12971086034d53c0c3dfbad07665abe
+Author: tb@openbsd.org <tb@openbsd.org>
+Date: Sun Jan 20 02:01:59 2019 +0000
- upstream: fix leaks in unit test; with this, all unit tests are
+ upstream: Fix BN_is_prime_* calls in SSH, the API returns -1 on
- leak free (as far as valgrind can spot anyway)
+ error.
- OpenBSD-Regress-ID: b824d8b27998365379963440e5d18b95ca03aa17
+ Found thanks to BoringSSL's commit 53409ee3d7595ed37da472bc73b010cd2c8a5ffd
+ by David Benjamin.
+
+ ok djm, dtucker
+
+ OpenBSD-Commit-ID: 1ee832be3c44b1337f76b8562ec6d203f3b072f8
-commit 2f6accff5085eb79b0dbe262d8b85ed017d1a51c
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 13 11:39:25 2018 +1000
+commit ec4776bb01dd8d61fddc7d2a31ab10bf3d3d829a
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Jan 20 01:12:40 2019 +0000
- Enable leak checks for unit tests with valgrind
+ upstream: DH-GEX min value is now specified in RFC8270. ok djm@
- Leave the leak checking on unconditionally when running with valgrind.
- The unit tests are leak-free and I want them to stay that way.
+ OpenBSD-Commit-ID: 1229d0feb1d0ecefe05bf67a17578b263e991acc
-commit e46cfbd9db5e907b821bf4fd0184d4dab99815ee
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 13 11:38:59 2018 +1000
+commit c90a7928c4191303e76a8c58b9008d464287ae1b
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Jan 21 09:22:36 2019 +1100
- increase timeout to match cfgmatch.sh
+ Check for cc before gcc.
- lets test pass under valgrind (on my workstation at least)
+ If cc is something other than gcc and is the system compiler prefer using
+ that, unless otherwise told via $CC. ok djm@
-commit 6aa1bf475cf3e7a2149acc5a1e80e904749f064c
+commit 9b655dc9c9a353f0a527f0c6c43a5e35653c9503
Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 12 14:54:18 2018 +1000
+Date: Sun Jan 20 14:55:27 2019 +1100
- rm regress/misc/kexfuzz/*.o in distclean target
+ last bits of old packet API / active_state global
-commit eef1447ddb559c03725a23d4aa6d03f40e8b0049
+commit 3f0786bbe73609ac96e5a0d91425ee21129f8e04
Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 12 14:49:26 2018 +1000
+Date: Sun Jan 20 10:22:18 2019 +1100
- repair !WITH_OPENSSL build
+ remove PAM dependencies on old packet API
+
+ Requires some caching of values, because the PAM code isn't
+ always called with packet context.
-commit 4d3b2f36fd831941d1627ac587faae37b6d3570f
+commit 08f66d9f17e12c1140d1f1cf5c4dce67e915d3cc
Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jul 12 14:49:14 2018 +1000
+Date: Sun Jan 20 09:58:45 2019 +1100
- missing headers
+ remove vestiges of old packet API from loginrec.c
-commit 3f420a692b293921216549c1099c2e46ff284eae
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Jul 12 14:57:46 2018 +1000
+commit c327813ea1d740e3e367109c17873815aba1328e
+Author: Damien Miller <djm@mindrot.org>
+Date: Sun Jan 20 09:45:38 2019 +1100
- Remove key.h from portable files too.
+ depend
+
+commit 135e302cfdbe91817294317c337cc38c3ff01cba
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 22:30:52 2019 +0000
+
+ upstream: fix error in refactor: use ssh_packet_disconnect() instead of
- Commit 5467fbcb removed key.h so stop including it in portable files
- too. Fixes builds on lots of platforms.
+ sshpkt_error(). The first one logs the error and exits (what we want) instead
+ of just logging and blundering on.
+
+ OpenBSD-Commit-ID: 39f51b43641dce9ce0f408ea6c0e6e077e2e91ae
-commit e2c4af311543093f16005c10044f7e06af0426f0
+commit 245c6a0b220b58686ee35bc5fc1c359e9be2faaa
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jul 12 04:35:25 2018 +0000
+Date: Sat Jan 19 21:45:31 2019 +0000
- upstream: remove prototype to long-gone function
+ upstream: remove last traces of old packet API!
- OpenBSD-Commit-ID: 0414642ac7ce01d176b9f359091a66a8bbb640bd
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 9bd10437026423eb8245636ad34797a20fbafd7d
-commit 394a842e60674bf8ee5130b9f15b01452a0b0285
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jul 11 18:55:11 2018 +0000
+commit 04c091fc199f17dacf8921df0a06634b454e2722
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:43:56 2019 +0000
- upstream: treat ssh_packet_write_wait() errors as fatal; ok djm@
+ upstream: remove last references to active_state
- OpenBSD-Commit-ID: f88ba43c9d54ed2d911218aa8d3f6285430629c3
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 78619a50ea7e4ca2f3b54d4658b3227277490ba2
-commit 5467fbcb09528ecdcb914f4f2452216c24796790
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jul 11 18:53:29 2018 +0000
+commit ec00f918b8ad90295044266c433340a8adc93452
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:43:07 2019 +0000
- upstream: remove legacy key emulation layer; ok djm@
+ upstream: convert monitor.c to new packet API
- OpenBSD-Commit-ID: 2b1f9619259e222bbd4fe9a8d3a0973eafb9dd8d
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 61ecd154bd9804461a0cf5f495a29d919e0014d5
-commit 5dc4c59d5441a19c99e7945779f7ec9051126c25
-Author: martijn@openbsd.org <martijn@openbsd.org>
-Date: Wed Jul 11 08:19:35 2018 +0000
+commit 6350e0316981489d4205952d6904d6fedba5bfe0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:42:30 2019 +0000
- upstream: s/wuth/with/ in comment
+ upstream: convert sshd.c to new packet API
- OpenBSD-Commit-ID: 9de41468afd75f54a7f47809d2ad664aa577902c
+ with & ok markus@
+
+ OpenBSD-Commit-ID: ea569d3eaf9b5cf1bad52779fbfa5fa0b28af891
-commit 1c688801e9dd7f9889fb2a29bc2b6fbfbc35a11f
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Jul 11 12:12:38 2018 +1000
+commit a5e2ad88acff2b7d131ee6d5dc5d339b0f8c6a6d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:41:53 2019 +0000
- Include stdlib.h for declaration of free.
+ upstream: convert session.c to new packet API
- Fixes build with -Werror on at least Fedora and probably others.
+ with & ok markus@
+
+ OpenBSD-Commit-ID: fae817207e23099ddd248960c984f7b7f26ea68e
-commit fccfa239def497615f92ed28acc57cfe63da3666
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 11 10:19:56 2018 +1000
+commit 3a00a921590d4c4b7e96df11bb10e6f9253ad45e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:41:18 2019 +0000
- VALGRIND_CHECK_LEAKS logic was backwards :(
+ upstream: convert auth.c to new packet API
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 7e10359f614ff522b52a3f05eec576257794e8e4
-commit 416287d45fcde0a8e66eee8b99aa73bd58607588
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Jul 11 10:10:26 2018 +1000
+commit 7ec5cb4d15ed2f2c5c9f5d00e6b361d136fc1e2d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:40:48 2019 +0000
- Fix sshbuf_new error path in skey.
+ upstream: convert serverloop.c to new packet API
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: c92dd19b55457541478f95c0d6b318426d86d885
-commit 7aab109b8b90a353c1af780524f1ac0d3af47bab
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Jul 11 10:06:18 2018 +1000
+commit 64c9598ac05332d1327cbf55334dee4172d216c4
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:40:21 2019 +0000
- Supply missing third arg in skey.
+ upstream: convert the remainder of sshconnect2.c to new packet
- During the change to the new buffer api the third arg to
- sshbuf_get_cstring was ommitted. Fixes build when configured with skey.
+ API
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 0986d324f2ceb5e8a12ac21c1bb10b3b4b1e0f71
-commit 380320bb72cc353a901790ab04b6287fd335dc4a
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Jul 11 10:03:34 2018 +1000
+commit bc5e1169d101d16e3a5962a928db2bc49a8ef5a3
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:39:12 2019 +0000
- Supply some more missing "int r" in skey
+ upstream: convert the remainder of clientloop.c to new packet API
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: ce2fbbacb86a290f31da1e7bf04cddf2bdae3d1e
-commit d20720d373d8563ee737d1a45dc5e0804d622dbc
+commit 5ebce136a6105f084db8f0d7ee41981d42daec40
Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jul 11 09:56:36 2018 +1000
+Date: Sun Jan 20 09:44:53 2019 +1100
- disable valgrind memleak checking by default
+ upstream: convert auth2.c to new packet API
- Add VALGRIND_CHECK_LEAKS knob to turn it back on.
+ OpenBSD-Commit-ID: ed831bb95ad228c6791bc18b60ce7a2edef2c999
-commit 79c9d35018f3a5e30ae437880b669aa8636cd3cd
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Jul 11 09:54:00 2018 +1000
+commit 172a592a53ebe8649c4ac0d7946e6c08eb151af6
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:37:48 2019 +0000
- Supply missing "int r" in skey code.
+ upstream: convert servconf.c to new packet API
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 126553aecca302c9e02fd77e333b9cb217e623b4
-commit 984bacfaacbbe31c35191b828fb5b5b2f0362c36
-Author: sf@openbsd.org <sf@openbsd.org>
-Date: Tue Jul 10 09:36:58 2018 +0000
+commit 8cc7a679d29cf6ecccfa08191e688c7f81ef95c2
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:37:13 2019 +0000
- upstream: re-remove some pre-auth compression bits
-
- This time, make sure to not remove things that are necessary for
- pre-auth compression on the client. Add a comment that pre-auth
- compression is still supported in the client.
+ upstream: convert channels.c to new packet API
- ok markus@
+ with & ok markus@
- OpenBSD-Commit-ID: 282c6fec7201f18a5c333bbb68d9339734d2f784
+ OpenBSD-Commit-ID: 0b8279b56113cbd4011fc91315c0796b63dc862c
-commit 120a1ec74e8d9d29f4eb9a27972ddd22351ddef9
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jul 10 19:39:52 2018 +1000
+commit 06232038c794c7dfcb087be0ab0b3e65b09fd396
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:36:38 2019 +0000
- Adapt portable to legacy buffer API removal
+ upstream: convert sshconnect.c to new packet API
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 222337cf6c96c347f1022d976fac74b4257c061f
-commit 0f3958c1e6ffb8ea4ba27e2a97a00326fce23246
+commit 25b2ed667216314471bb66752442c55b95792dc3
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 10 09:13:30 2018 +0000
+Date: Sat Jan 19 21:36:06 2019 +0000
- upstream: kerberos/gssapi fixes for buffer removal
+ upstream: convert ssh.c to new packet API
- OpenBSD-Commit-ID: 1cdf56fec95801e4563c47f21696f04cd8b60c4c
+ with & ok markus@
+
+ OpenBSD-Commit-ID: eb146878b24e85c2a09ee171afa6797c166a2e21
-commit c74ae8e7c45f325f3387abd48fa7dfef07a08069
+commit e3128b38623eef2fa8d6e7ae934d3bd08c7e973e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 10 06:45:29 2018 +0000
+Date: Sat Jan 19 21:35:25 2019 +0000
- upstream: buffer.[ch] and bufaux.c are no more
+ upstream: convert mux.c to new packet API
- OpenBSD-Commit-ID: d1a1852284e554f39525eb4d4891b207cfb3d3a0
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 4e3893937bae66416e984b282d8f0f800aafd802
-commit a881e5a133d661eca923fb0633a03152ab2b70b2
+commit ed1df7226caf3a943a36d580d4d4e9275f8a61ee
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 10 06:43:52 2018 +0000
+Date: Sat Jan 19 21:34:45 2019 +0000
- upstream: one mention of Buffer that almost got away :)
+ upstream: convert sshconnect2.c to new packet API
- OpenBSD-Commit-ID: 30d7c27a90b4544ad5dfacf654595710cd499f02
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 1cb869e0d6e03539f943235641ea070cae2ebc58
-commit 49f47e656b60bcd1d1db98d88105295f4b4e600d
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:59:10 2018 +0000
+commit 23f22a4aaa923c61ec49a99ebaa383656e87fa40
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:33:57 2019 +0000
- upstream: replace cast with call to sshbuf_mutable_ptr(); ok djm@
+ upstream: convert clientloop.c to new packet API
- OpenBSD-Commit-ID: 4dfe9d29fa93d9231645c89084f7217304f7ba29
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 497b36500191f452a22abf283aa8d4a9abaee7fa
-commit cb30cd47041edb03476be1c8ef7bc1f4b69d1555
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:56:06 2018 +0000
+commit ad60b1179c9682ca5aef0b346f99ef68cbbbc4e5
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:33:13 2019 +0000
- upstream: remove legacy buffer API emulation layer; ok djm@
+ upstream: allow sshpkt_fatal() to take a varargs format; we'll
- OpenBSD-Commit-ID: 2dd5dc17cbc23195be4299fa93be2707a0e08ad9
+ use this to give packet-related fatal error messages more context (esp. the
+ remote endpoint) ok markus@
+
+ OpenBSD-Commit-ID: de57211f9543426b515a8a10a4f481666b2b2a50
-commit 235c7c4e3bf046982c2d8242f30aacffa01073d1
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:53:45 2018 +0000
+commit 0fa174ebe129f3d0aeaf4e2d1dd8de745870d0ff
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jan 19 21:31:32 2019 +0000
- upstream: sshd: switch monitor to sshbuf API; lots of help & ok
+ upstream: begin landing remaining refactoring of packet parsing
- djm@
+ API, started almost exactly six years ago.
- OpenBSD-Commit-ID: d89bd02d33974fd35ca0b8940d88572227b34a48
+ This change stops including the old packet_* API by default and makes
+ each file that requires the old API include it explicitly. We will
+ commit file-by-file refactoring to remove the old API in consistent
+ steps.
+
+ with & ok markus@
+
+ OpenBSD-Commit-ID: 93c98a6b38f6911fd1ae025a1ec57807fb4d4ef4
-commit b8d9214d969775e409e1408ecdf0d58fad99b344
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:37:55 2018 +0000
+commit 4ae7f80dfd02f2bde912a67c9f338f61e90fa79f
+Author: tb@openbsd.org <tb@openbsd.org>
+Date: Sat Jan 19 04:15:56 2019 +0000
- upstream: sshd: switch GSSAPI to sshbuf API; ok djm@
+ upstream: Print an \r in front of the password prompt so parts of
- OpenBSD-Commit-ID: e48449ab4be3f006f7ba33c66241b7d652973e30
+ a password that was entered too early are likely clobbered by the prompt.
+ Idea from doas.
+
+ from and ok djm
+ "i like it" deraadt
+
+ OpenBSD-Commit-ID: 5fb97c68df6d8b09ab37f77bca1d84d799c4084e
-commit c7d39ac8dc3587c5f05bdd5bcd098eb5c201c0c8
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:35:50 2018 +0000
+commit a6258e5dc314c7d504ac9f0fbc3be96475581dbe
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Jan 18 11:09:01 2019 +1100
- upstream: sshd: switch authentication to sshbuf API; ok djm@
+ Add minimal fchownat and fchmodat implementations.
- OpenBSD-Commit-ID: 880aa06bce4b140781e836bb56bec34873290641
+ Fixes builds on at least OS X Lion, NetBSD 6 and Solaris 10.
-commit c3cb7790e9efb14ba74b2d9f543ad593b3d55b31
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:29:36 2018 +0000
+commit 091093d25802b87d3b2b09f2c88d9f33e1ae5562
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Jan 18 12:11:42 2019 +1300
- upstream: sshd: switch config to sshbuf API; ok djm@
+ Add a minimal implementation of utimensat().
- OpenBSD-Commit-ID: 72b02017bac7feac48c9dceff8355056bea300bd
+ Some systems (eg older OS X) do not have utimensat, so provide minimal
+ implementation in compat layer. Fixes build on at least El Capitan.
-commit 2808d18ca47ad3d251836c555f0e22aaca03d15c
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:26:02 2018 +0000
+commit 609644027dde1f82213699cb6599e584c7efcb75
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jan 1 22:20:16 2019 +0000
- upstream: sshd: switch loginmsg to sshbuf API; ok djm@
+ upstream: regress bits for banner processing refactor (this test was
- OpenBSD-Commit-ID: f3cb4e54bff15c593602d95cc43e32ee1a4bac42
+ depending on ssh returning a particular error message for banner parsing
+ failure)
+
+ reminded by bluhm@
+
+ OpenBSD-Regress-ID: f24fc303d40931157431df589b386abf5e1be575
-commit 89dd615b8b531979be63f05f9d5624367c9b28e6
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:20:26 2018 +0000
+commit f47d72ddad75b93d3cbc781718b0fa9046c03df8
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jan 17 04:45:09 2019 +0000
- upstream: ttymodes: switch to sshbuf API; ok djm@
+ upstream: tun_fwd_ifnames variable should b
- OpenBSD-Commit-ID: 5df340c5965e822c9da21e19579d08dea3cbe429
-
-commit f4608a7065480516ab46214f554e5f853fb7870f
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:18:10 2018 +0000
-
- upstream: client: switch mux to sshbuf API; with & ok djm@
+ =?UTF-8?q?e=20extern;=20from=20Hanno=20B=C3=B6ck?=
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset=UTF-8
+ Content-Transfer-Encoding: 8bit
- OpenBSD-Commit-ID: 5948fb98d704f9c4e075b92edda64e0290b5feb2
+ OpenBSD-Commit-ID: d53dede6e521161bf04d39d09947db6253a38271
-commit cecee2d607099a7bba0a84803e2325d15be4277b
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 21:03:30 2018 +0000
+commit 943d0965263cae1c080ce5a9d0b5aa341885e55d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jan 17 04:20:53 2019 +0000
- upstream: client: switch to sshbuf API; ok djm@
+ upstream: include time.h for time(3)/nanosleep(2); from Ian
- OpenBSD-Commit-ID: 60cb0356114acc7625ab85105f6f6a7cd44a8d05
-
-commit ff55f4ad898137d4703e7a2bcc81167dfe8e9324
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jul 9 20:39:28 2018 +0000
-
- upstream: pkcs11: switch to sshbuf API; ok djm@
+ McKellar
- OpenBSD-Commit-ID: 98cc4e800f1617c51caf59a6cb3006f14492db79
+ OpenBSD-Commit-ID: 6412ccd06a88f65b207a1089345f51fa1244ea51
-commit 168b46f405d6736960ba7930389eecb9b6710b7e
-Author: sf@openbsd.org <sf@openbsd.org>
-Date: Mon Jul 9 13:37:10 2018 +0000
+commit dbb4dec6d5d671b5e9d67ef02162a610ad052068
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jan 17 01:50:24 2019 +0000
- upstream: Revert previous two commits
-
- It turns out we still support pre-auth compression on the client.
- Therefore revert the previous two commits:
-
- date: 2018/07/06 09:06:14; author: sf; commitid: yZVYKIRtUZWD9CmE;
- Rename COMP_DELAYED to COMP_ZLIB
+ upstream: many of the global variables in this file can be made static;
- Only delayed compression is supported nowadays.
-
- ok markus@
+ patch from Markus Schmidt
- date: 2018/07/06 09:05:01; author: sf; commitid: rEGuT5UgI9f6kddP;
- Remove leftovers from pre-authentication compression
+ OpenBSD-Commit-ID: f3db619f67beb53257b21bac0e92b4fb7d5d5737
+
+commit 60d8c84e0887514c99c9ce071965fafaa1c3d34a
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jan 16 23:23:45 2019 +0000
+
+ upstream: Add "-h" flag to sftp chown/chgrp/chmod commands to
- Support for this has been removed in 2016.
- COMP_DELAYED will be renamed in a later commit.
+ request they do not follow symlinks. Requires recently-committed
+ lsetstat@openssh.com extension on the server side.
- ok markus@
+ ok markus@ dtucker@
- OpenBSD-Commit-ID: cdfef526357e4e1483c86cf599491b2dafb77772
+ OpenBSD-Commit-ID: f93bb3f6f7eb2fb7ef1e59126e72714f1626d604
-commit ab39267fa1243d02b6c330615539fc4b21e17dc4
-Author: sf@openbsd.org <sf@openbsd.org>
-Date: Fri Jul 6 09:06:14 2018 +0000
+commit dbbc7e0eab7262f34b8e0cd6efecd1c77b905ed0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jan 16 23:22:10 2019 +0000
- upstream: Rename COMP_DELAYED to COMP_ZLIB
+ upstream: add support for a "lsetstat@openssh.com" extension. This
- Only delayed compression is supported nowadays.
+ replicates the functionality of the existing SSH2_FXP_SETSTAT operation but
+ does not follow symlinks. Based on a patch from Bert Haverkamp in bz#2067 but
+ with more attribute modifications supported.
- ok markus@
+ ok markus@ dtucker@
- OpenBSD-Commit-ID: 5b1dbaf3d9a4085aaa10fec0b7a4364396561821
+ OpenBSD-Commit-ID: f7234f6e90db19655d55d936a115ee4ccb6aaf80
-commit 95db395d2e56a6f868193aead6cadb2493f036c6
-Author: sf@openbsd.org <sf@openbsd.org>
-Date: Fri Jul 6 09:05:01 2018 +0000
+commit 4a526941d328fc3d97068c6a4cbd9b71b70fe5e1
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jan 4 03:27:50 2019 +0000
- upstream: Remove leftovers from pre-authentication compression
-
- Support for this has been removed in 2016.
- COMP_DELAYED will be renamed in a later commit.
+ upstream: eliminate function-static attempt counters for
- ok markus@
+ passwd/kbdint authmethods by moving them to the client authctxt; Patch from
+ Markus Schmidt, ok markus@
- OpenBSD-Commit-ID: 6a99616c832627157113fcb0cf5a752daf2e6b58
+ OpenBSD-Commit-ID: 4df4404a5d5416eb056f68e0e2f4fa91ba3b3f7f
-commit f28a4d5cd24c4aa177e96b4f96957991e552cb70
-Author: sf@openbsd.org <sf@openbsd.org>
-Date: Fri Jul 6 09:03:02 2018 +0000
+commit 8a8183474c41bd6cebaa917346b549af2239ba2f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jan 4 03:23:00 2019 +0000
- upstream: Remove unused ssh_packet_start_compression()
+ upstream: fix memory leak of ciphercontext when rekeying; bz#2942
- ok markus@
+ Patch from Markus Schmidt; ok markus@
- OpenBSD-Commit-ID: 9d34cf2f59aca5422021ae2857190578187dc2b4
+ OpenBSD-Commit-ID: 7877f1b82e249986f1ef98d0ae76ce987d332bdd
-commit 872517ddbb72deaff31d4760f28f2b0a1c16358f
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jul 6 13:32:02 2018 +1000
+commit 5bed70afce0907b6217418d0655724c99b683d93
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jan 1 23:10:53 2019 +0000
- Defer setting bufsiz in getdelim.
+ upstream: static on global vars, const on handler tables that contain
- Do not write to bufsiz until we are sure the malloc has succeeded,
- in case any callers rely on it (which they shouldn't). ok djm@
+ function pointers; from Mike Frysinger
+
+ OpenBSD-Commit-ID: 7ef2305e50d3caa6326286db43cf2cfaf03960e0
-commit 3deb56f7190a414dc264e21e087a934fa1847283
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Jul 5 13:32:01 2018 +1000
+commit 007a88b48c97d092ed2f501bbdcb70d9925277be
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Dec 27 23:02:11 2018 +0000
- Fix other callers of read_environment_file.
+ upstream: Request RSA-SHA2 signatures for
- read_environment_file recently gained an extra argument Some platform
- specific code also calls it so add the argument to those too. Fixes
- build on Solaris and AIX.
+ rsa-sha2-{256|512}-cert-v01@openssh.com cert algorithms; ok markus@
+
+ OpenBSD-Commit-ID: afc6f7ca216ccd821656d1c911d2a3deed685033
-commit 314908f451e6b2d4ccf6212ad246fa4619c721d3
+commit eb347d086c35428c47fe52b34588cbbc9b49d9a6
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jul 4 13:51:45 2018 +0000
+Date: Thu Dec 27 03:37:49 2018 +0000
- upstream: deal with API rename: match_filter_list() =>
+ upstream: ssh_packet_set_state() now frees ssh->kex implicitly, so
- match_filter_blacklist()
+ don't do explicit kex_free() beforehand
- OpenBSD-Regress-ID: 2da342be913efeb51806351af906fab01ba4367f
+ OpenBSD-Regress-ID: f2f73bad47f62a2040ccba0a72cadcb12eda49cf
-commit 89f54cdf6b9cf1cf5528fd33897f1443913ddfb4
+commit bb542f0cf6f7511a22a08c492861e256a82376a9
+Author: tedu@openbsd.org <tedu@openbsd.org>
+Date: Sat Dec 15 00:50:21 2018 +0000
+
+ upstream: remove unused and problematic sudo clean. ok espie
+
+ OpenBSD-Regress-ID: ca90c20a15a85b661e13e98b80c10e65cd662f7b
+
+commit 0a843d9a0e805f14653a555f5c7a8ba99d62c12d
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jul 4 13:51:12 2018 +0000
+Date: Thu Dec 27 03:25:24 2018 +0000
- upstream: exercise new expansion behaviour of
+ upstream: move client/server SSH-* banners to buffers under
- PubkeyAcceptedKeyTypes and, by proxy, test kex_assemble_names()
+ ssh->kex and factor out the banner exchange. This eliminates some common code
+ from the client and server.
- ok markus@
+ Also be more strict about handling \r characters - these should only
+ be accepted immediately before \n (pointed out by Jann Horn).
- OpenBSD-Regress-ID: 292978902e14d5729aa87e492dd166c842f72736
+ Inspired by a patch from Markus Schmidt.
+ (lots of) feedback and ok markus@
+
+ OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b
-commit 187633f24c71564e970681c8906df5a6017dcccf
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 13:53:26 2018 +0000
+commit 434b587afe41c19391821e7392005068fda76248
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Dec 7 04:36:09 2018 +0000
- upstream: add a comment that could have saved me 45 minutes of wild
+ upstream: Fix calculation of initial bandwidth limits. Account for
- goose chasing
+ written bytes before the initial timer check so that the first buffer written
+ is accounted. Set the threshold after which the timer is checked such that
+ the limit starts being computed as soon as possible, ie after the second
+ buffer is written. This prevents an initial burst of traffic and provides a
+ more accurate bandwidth limit. bz#2927, ok djm.
- OpenBSD-Regress-ID: d469b29ffadd3402c090e21b792d627d46fa5297
+ OpenBSD-Commit-ID: ff3ef76e4e43040ec198c2718d5682c36b255cb6
-commit 312d2f2861a2598ed08587cb6c45c0e98a85408f
+commit a6a0788cbbe8dfce2819ee43b09c80725742e21c
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jul 4 13:49:31 2018 +0000
+Date: Fri Dec 7 03:39:40 2018 +0000
- upstream: repair PubkeyAcceptedKeyTypes (and friends) after RSA
-
- signature work - returns ability to add/remove/specify algorithms by
- wildcard.
+ upstream: only consider the ext-info-c extension during the initial
- Algorithm lists are now fully expanded when the server/client configs
- are finalised, so errors are reported early and the config dumps
- (e.g. "ssh -G ...") now list the actual algorithms selected.
+ KEX. It shouldn't be sent in subsequent ones, but if it is present we should
+ ignore it.
- Clarify that, while wildcards are accepted in algorithm lists, they
- aren't full pattern-lists that support negation.
+ This prevents sshd from sending a SSH_MSG_EXT_INFO for REKEX for buggy
+ these clients. Reported by Jakub Jelen via bz2929; ok dtucker@
- (lots of) feedback, ok markus@
+ OpenBSD-Commit-ID: 91564118547f7807030ec537480303e2371902f9
+
+commit 63bba57a32c5bb6158d57cf4c47022daf89c14a0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Dec 7 03:33:18 2018 +0000
+
+ upstream: fix option letter pasto in previous
- OpenBSD-Commit-ID: a8894c5c81f399a002f02ff4fe6b4fa46b1f3207
+ OpenBSD-Commit-ID: e26c8bf2f2a808f3c47960e1e490d2990167ec39
-commit 303af5803bd74bf05d375c04e1a83b40c30b2be5
+commit 737e4edd82406595815efadc28ed5161b8b0c01a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 11:43:49 2018 +0000
+Date: Fri Dec 7 03:32:26 2018 +0000
- upstream: some magic for RSA-SHA2 checks
+ upstream: mention that the ssh-keygen -F (find host in
- OpenBSD-Regress-ID: e5a9b11368ff6d86e7b25ad10ebe43359b471cd4
+ authorized_keys) and -R (remove host from authorized_keys) options may accept
+ either a bare hostname or a [hostname]:port combo. bz#2935
+
+ OpenBSD-Commit-ID: 5535cf4ce78375968b0d2cd7aa316fa3eb176780
-commit 7d68e262944c1fff1574600fe0e5e92ec8b398f5
+commit 8a22ffaa13391cfe5b40316d938fe0fb931e9296
Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jul 3 23:27:11 2018 +1000
+Date: Fri Dec 7 15:41:16 2018 +1100
- depend
+ expose $SSH_CONNECTION in the PAM environment
+
+ This makes the connection 4-tuple available to PAM modules that
+ wish to use it in decision-making. bz#2741
-commit b4d4eda633af433d20232cbf7e855ceac8b83fe5
+commit a784fa8c7a7b084d63bae82ccfea902131bb45c5
+Author: Kevin Adler <kadler@us.ibm.com>
+Date: Wed Dec 12 22:12:45 2018 -0600
+
+ Don't pass loginmsg by address now that it's an sshbuf*
+
+ In 120a1ec74, loginmsg was changed from the legacy Buffer type
+ to struct sshbuf*, but it missed changing calls to
+ sys_auth_allowed_user and sys_auth_record_login which passed
+ loginmsg by address. Now that it's a pointer, just pass it directly.
+
+ This only affects AIX, unless there are out of tree users.
+
+commit 285310b897969a63ef224d39e7cc2b7316d86940
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 13:20:25 2018 +0000
+Date: Fri Dec 7 02:31:20 2018 +0000
- upstream: some finesse to fix RSA-SHA2 certificate authentication
+ upstream: no need to allocate channels_pre/channels_post in
- for certs hosted in ssh-agent
+ channel_init_channels() as we do it anyway in channel_handler_init() that we
+ call at the end of the function. Fix from Markus Schmidt via bz#2938
- OpenBSD-Commit-ID: e5fd5edd726137dda2d020e1cdebc464110a010f
+ OpenBSD-Commit-ID: 74893638af49e3734f1e33a54af1b7ea533373ed
-commit d78b75df4a57e0f92295f24298e5f2930e71c172
+commit 87d6cf1cbc91df6815db8fe0acc7c910bc3d18e4
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 13:07:58 2018 +0000
+Date: Fri Nov 30 02:24:52 2018 +0000
- upstream: check correct variable; unbreak agent keys
+ upstream: don't attempt to connect to empty SSH_AUTH_SOCK; bz#293
- OpenBSD-Commit-ID: c36981fdf1f3ce04966d3310826a3e1e6233d93e
+ OpenBSD-Commit-ID: 0e8fc8f19f14b21adef7109e0faa583d87c0e929
-commit 2f30300c5e15929d0e34013f38d73e857f445e12
+commit 91b19198c3f604f5eef2c56dbe36f29478243141
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 11:42:12 2018 +0000
+Date: Wed Nov 28 06:00:38 2018 +0000
- upstream: crank version number to 7.8; needed for new compat flag
+ upstream: don't truncate user or host name in "user@host's
- for prior version; part of RSA-SHA2 strictification, ok markus@
+ OpenBSD-Commit-ID: e6ca01a8d58004b7f2cac0b1b7ce8f87e425e360
+
+commit dd0cf6318d9b4b3533bda1e3bc021b2cd7246b7a
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Nov 23 06:58:28 2018 +0000
+
+ upstream: tweak previous;
- OpenBSD-Commit-ID: 84a11fc0efd2674c050712336b5093f5d408e32b
+ OpenBSD-Commit-ID: 08f096922eb00c98251501c193ff9e83fbb5de4f
-commit 4ba0d54794814ec0de1ec87987d0c3b89379b436
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 11:39:54 2018 +0000
+commit 8a85f5458d1c802471ca899c97f89946f6666e61
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Nov 25 21:44:05 2018 +1100
- upstream: Improve strictness and control over RSA-SHA2 signature
+ Include stdio.h for FILE if needed.
+
+commit 16fb23f25454991272bfe4598cc05d20fcd25116
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Nov 25 14:05:57 2018 +1100
+
+ Reverse order of OpenSSL init functions.
- In ssh, when an agent fails to return a RSA-SHA2 signature when
- requested and falls back to RSA-SHA1 instead, retry the signature to
- ensure that the public key algorithm sent in the SSH_MSG_USERAUTH
- matches the one in the signature itself.
+ Try the new init function (OPENSSL_init_crypto) before falling back to
+ the old one (OpenSSL_add_all_algorithms).
+
+commit 98f878d2272bf8dff21f2a0265d963c29e33fed2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Nov 25 14:05:08 2018 +1100
+
+ Improve OpenSSL_add_all_algorithms check.
- In sshd, strictly enforce that the public key algorithm sent in the
- SSH_MSG_USERAUTH message matches what appears in the signature.
+ OpenSSL_add_all_algorithms() may be a macro so check for that too.
+
+commit 9e34e0c59ab04514f9de9934a772283f7f372afe
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Nov 23 05:08:07 2018 +0000
+
+ upstream: add a ssh_config "Match final" predicate
- Make the sshd_config PubkeyAcceptedKeyTypes and
- HostbasedAcceptedKeyTypes options control accepted signature algorithms
- (previously they selected supported key types). This allows these
- options to ban RSA-SHA1 in favour of RSA-SHA2.
+ Matches in same pass as "Match canonical" but doesn't require
+ hostname canonicalisation be enabled. bz#2906 ok markus
- Add new signature algorithms "rsa-sha2-256-cert-v01@openssh.com" and
- "rsa-sha2-512-cert-v01@openssh.com" to force use of RSA-SHA2 signatures
- with certificate keys.
+ OpenBSD-Commit-ID: fba1dfe9f6e0cabcd0e2b3be13f7a434199beffa
+
+commit 4da58d58736b065b1182b563d10ad6765d811c6d
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Nov 23 02:53:57 2018 +0000
+
+ upstream: Remove now-unneeded ifdef SIGINFO around handler since it is
- feedback and ok markus@
+ now always used for SIGUSR1 even when SIGINFO is not defined. This will make
+ things simpler in -portable.
- OpenBSD-Commit-ID: c6e9f6d45eed8962ad502d315d7eaef32c419dde
+ OpenBSD-Regress-ID: 4ff0265b335820b0646d37beb93f036ded0dc43f
-commit 95344c257412b51199ead18d54eaed5bafb75617
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jul 3 10:59:35 2018 +0000
+commit c721d5877509875c8515df0215fa1dab862013bc
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Nov 23 14:11:20 2018 +1100
- upstream: allow sshd_config PermitUserEnvironment to accept a
+ Move RANDOM_SEED_SIZE outside ifdef.
- pattern-list of whitelisted environment variable names in addition to yes|no.
+ RANDOM_SEED_SIZE is used by both the OpenSSL and non-OpenSSL code
+ This fixes the build with configureed --without-openssl.
+
+commit deb51552c3ce7ce72c8d0232e4f36f2e7c118c7d
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Nov 22 19:59:28 2018 +1100
+
+ Resync with OpenBSD by pulling in an ifdef SIGINFO.
+
+commit 28c7b2cd050f4416bfcf3869a20e3ea138aa52fe
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Nov 23 10:45:20 2018 +1100
+
+ fix configure test for OpenSSL version
- bz#1800, feedback and ok markus@
+ square brackets in case statements may be eaten by autoconf.
- OpenBSD-Commit-ID: 77dc2b468e0bf04b53f333434ba257008a1fdf24
+ Report and fix from Filipp Gunbin; tweaked by naddy@
-commit 6f56fe4b9578b0627667f8bce69d4d938a88324c
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Tue Jun 26 11:23:59 2018 +0000
+commit 42c5ec4b97b6a1bae70f323952d0646af16ce710
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Nov 23 10:40:06 2018 +1100
- upstream: Fix "WARNING: line 6 disappeared in /etc/moduli, giving up"
+ refactor libcrypto initialisation
- when choosing a prime. An extra increment of linenum snuck in as part of the
- conversion to getline(). OK djm@ markus@
+ Don't call OpenSSL_add_all_algorithms() unless OpenSSL actually
+ supports it.
- OpenBSD-Commit-ID: 0019225cb52ed621b71cd9f19ee2e78e57e3dd38
+ Move all libcrypto initialisation to a single function, and call that
+ from seed_rng() that is called early in each tool's main().
+
+ Prompted by patch from Rosen Penev
-commit 1eee79a11c1b3594f055b01e387c49c9a6e80005
+commit 5b60b6c02009547a3e2a99d4886965de2a4719da
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Jul 2 14:13:30 2018 +0000
+Date: Thu Nov 22 08:59:11 2018 +0000
- upstream: One ampersand is enough to backgroud an process. OpenBSD
+ upstream: Output info on SIGUSR1 as well as
- doesn't seem to mind, but some platforms in -portable object to the second.
+ SIGINFO to resync with portable. (ID sync only).
- OpenBSD-Regress-ID: d6c3e404871764343761dc25c3bbe29c2621ff74
+ OpenBSD-Regress-ID: 699d153e2de22dce51a1b270c40a98472d1a1b16
-commit 6301e6c787d4e26bfae1119ab4f747bbcaa94e44
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Jul 2 21:16:58 2018 +1000
+commit e4ae345dc75b34fd870c2e8690d831d2c1088eb7
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Nov 22 08:48:32 2018 +0000
- Add implementation of getline.
+ upstream: Append pid to temp files in /var/run and set a cleanup
- Add getline for the benefit of platforms that don't have it. Sourced
- from NetBSD (OpenBSD's implementation is a little too chummy with the
- internals of FILE).
+ trap for them. This allows multiple instances of tests to run without
+ colliding.
+
+ OpenBSD-Regress-ID: 57add105ecdfc54752d8003acdd99eb68c3e0b4c
-commit 84623e0037628f9992839063151f7a9f5f13099a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jun 26 02:02:36 2018 +0000
+commit f72d0f52effca5aa20a193217346615ecd3eed53
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Oct 31 11:09:27 2018 +0000
- upstream: whitespace
+ upstream: UsePrivilegeSeparation no is deprecated
- OpenBSD-Commit-ID: 9276951caf4daf555f6d262e95720e7f79244572
+ test "yes" and "sandbox".
+
+ OpenBSD-Regress-ID: 80e685ed8990766527dc629b1affc09a75bfe2da
-commit 90e51d672711c19a36573be1785caf35019ae7a8
+commit 35d0e5fefc419bddcbe09d7fc163d8cd3417125b
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jun 25 22:28:33 2018 +0000
+Date: Wed Oct 17 23:28:05 2018 +0000
- upstream: fix NULL dereference in open_listen_match_tcpip()
+ upstream: add some knobs:
- OpenBSD-Commit-ID: c968c1d29e392352383c0f9681fcc1e93620c4a9
+ UNITTEST_FAST?= no # Skip slow tests (e.g. less intensive fuzzing).
+ UNITTEST_SLOW?= no # Include slower tests (e.g. more intensive fuzzing).
+ UNITTEST_VERBOSE?= no # Verbose test output (inc. per-test names).
+
+ useful if you want to run the tests as a smoke test to exercise the
+ functionality without waiting for all the fuzzers to run.
+
+ OpenBSD-Regress-ID: e04d82ebec86068198cd903acf1c67563c57315e
-commit f535ff922a67d9fcc5ee69d060d1b21c8bb01d14
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue Jun 19 05:36:57 2018 +0000
+commit c1941293d9422a14dda372b4c21895e72aa7a063
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Nov 22 15:52:26 2018 +1100
- upstream: spelling;
+ Resync Makefile.inc with upstream.
- OpenBSD-Commit-ID: db542918185243bea17202383a581851736553cc
+ It's unused in -portable, but having it out of sync makes other syncs
+ fail to apply.
-commit 80e199d6175904152aafc5c297096c3e18297691
+commit 928f1231f65f88cd4c73e6e0edd63d2cf6295d77
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jun 19 03:02:17 2018 +0000
+Date: Mon Nov 19 04:12:32 2018 +0000
- upstream: test PermitListen with bare port numbers
+ upstream: silence (to log level debug2) failure messages when
- OpenBSD-Regress-ID: 4b50a02dfb0ccaca08247f3877c444126ba901b3
-
-commit 87ddd676da0f3abd08b778b12b53b91b670dc93c
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jun 19 02:59:41 2018 +0000
-
- upstream: allow bare port numbers to appear in PermitListen directives,
+ loading the default hostkeys. Hostkeys explicitly specified in the
+ configuration or on the command-line are still reported as errors, and
+ failure to load at least one host key remains a fatal error.
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset=UTF-8
+ Content-Transfer-Encoding: 8bit
- e.g.
+ Based on patch from Dag-Erling Smørgrav via
+ https://github.com/openssh/openssh-portable/pull/103
- PermitListen 2222 8080
+ ok markus@
- is equivalent to:
+ OpenBSD-Commit-ID: ffc2e35a75d1008effaf05a5e27425041c27b684
+
+commit 7fca94edbe8ca9f879da9fdd2afd959c4180f4c7
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Nov 18 22:43:29 2018 +0000
+
+ upstream: Fix inverted logic for redirecting ProxyCommand stderr to
- PermitListen *:2222 *:8080
+ /dev/null. Fixes mosh in proxycommand mode that was broken by the previous
+ ProxyCommand change that was reported by matthieu@. ok djm@ danj@
- Some bonus manpage improvements, mostly from markus@
+ OpenBSD-Commit-ID: c6fc9641bc250221a0a81c6beb2e72d603f8add6
+
+commit ccef7c4faf914993b53035cd2b25ce02ab039c9d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Nov 16 06:17:38 2018 +0000
+
+ upstream: redirect stderr of ProxyCommands to /dev/null when ssh is
- "looks fine" markus@
+ started with ControlPersist; based on patch from Steffen Prohaska
- OpenBSD-Commit-ID: 6546b0cc5aab7f53d65ad0a348ca0ae591d6dd24
+ OpenBSD-Commit-ID: 1bcaa14a03ae80369d31021271ec75dce2597957
-commit 26f96ca10ad0ec5da9b05b99de1e1ccea15a11be
+commit 15182fd96845a03216d7ac5a2cf31c4e77e406e3
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 15 07:01:11 2018 +0000
+Date: Fri Nov 16 06:10:29 2018 +0000
- upstream: invalidate supplemental group cache used by
+ upstream: make grandparent-parent-child sshbuf chains robust to
- temporarily_use_uid() when the target uid differs; could cause failure to
- read authorized_keys under some configurations. patch by Jakub Jelen via
- bz2873; ok dtucker, markus
+ use-after-free faults if the ancestors are freed before the descendents.
+ Nothing in OpenSSH uses this deallocation pattern. Reported by Jann Horn
- OpenBSD-Commit-ID: 48a345f0ee90f6c465a078eb5e89566b23abd8a1
+ OpenBSD-Commit-ID: d93501d1d2734245aac802a252b9bb2eccdba0f2
-commit 89a85d724765b6b82e0135ee5a1181fdcccea9c6
+commit 2a35862e664afde774d4a72497d394fe7306ccb5
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jun 10 23:45:41 2018 +0000
+Date: Fri Nov 16 03:26:01 2018 +0000
- upstream: unbreak SendEnv; patch from tb@
+ upstream: use path_absolute() for pathname checks; from Manoj Ampalam
- OpenBSD-Commit-ID: fc808daced813242563b80976e1478de95940056
+ OpenBSD-Commit-ID: 482ce71a5ea5c5f3bc4d00fd719481a6a584d925
-commit acf4260f0951f89c64e1ebbc4c92f451768871ad
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Jun 9 06:36:31 2018 +0000
+commit d0d1dfa55be1c5c0d77ab3096b198a64235f936d
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Nov 16 14:11:44 2018 +1100
- upstream: sort previous;
+ Test for OPENSSL_init_crypto before using.
- OpenBSD-Commit-ID: 27d80d8b8ca99bc33971dee905e8ffd0053ec411
+ Check for the presence of OPENSSL_init_crypto and all the flags we want
+ before trying to use it (bz#2931).
-commit 1678d4236451060b735cb242d2e26e1ac99f0947
+commit 6010c0303a422a9c5fa8860c061bf7105eb7f8b2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 9 03:18:11 2018 +0000
+Date: Fri Nov 16 03:03:10 2018 +0000
- upstream: slightly better wording re handing of $TERM, from Jakub
+ upstream: disallow empty incoming filename or ones that refer to the
- Jelen via bz2386
+ current directory; based on report/patch from Harry Sintonen
- OpenBSD-Commit-ID: 14bea3f069a93c8be66a7b97794255a91fece964
+ OpenBSD-Commit-ID: f27651b30eaee2df49540ab68d030865c04f6de9
-commit 28013759f09ed3ebf7e8335e83a62936bd7a7f47
+commit aaed635e3a401cfcc4cc97f33788179c458901c3
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 9 03:03:10 2018 +0000
+Date: Fri Nov 16 02:46:20 2018 +0000
- upstream: add a SetEnv directive for sshd_config to allow an
-
- administrator to explicitly specify environment variables set in sessions
- started by sshd. These override the default environment and any variables set
- by user configuration (PermitUserEnvironment, etc), but not the SSH_*
- variables set by sshd itself.
+ upstream: fix bug in client that was keeping a redundant ssh-agent
- ok markus@
+ socket around for the life of the connection; bz#2912; reported by Simon
+ Tatham; ok dtucker@
- OpenBSD-Commit-ID: b6a96c0001ccd7dd211df6cae9e961c20fd718c0
+ OpenBSD-Commit-ID: 4ded588301183d343dce3e8c5fc1398e35058478
-commit 7082bb58a2eb878d23ec674587c742e5e9673c36
+commit e76135e3007f1564427b2956c628923d8dc2f75a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 9 03:01:12 2018 +0000
+Date: Fri Nov 16 02:43:56 2018 +0000
- upstream: add a SetEnv directive to ssh_config that allows setting
+ upstream: fix bug in HostbasedAcceptedKeyTypes and
- environment variables for the remote session (subject to the server accepting
- them)
+ PubkeyAcceptedKeyTypes options. If only RSA-SHA2 siganture types were
+ specified, then authentication would always fail for RSA keys as the monitor
+ checks only the base key (not the signature algorithm) type against
+ *AcceptedKeyTypes. bz#2746; reported by Jakub Jelen; ok dtucker
- refactor SendEnv to remove the arbitrary limit of variable names.
+ OpenBSD-Commit-ID: 117bc3dc54578dbdb515a1d3732988cb5b00461b
+
+commit 5c1a63562cac0574c226224075b0829a50b48c9d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Nov 16 02:30:20 2018 +0000
+
+ upstream: support a prefix of '@' to suppress echo of sftp batch
- ok markus@
+ commands; bz#2926; ok dtucker@
- OpenBSD-Commit-ID: cfbb00d9b0e10c1ffff1d83424351fd961d1f2be
+ OpenBSD-Commit-ID: 9d635636bc84aeae796467e059f7634de990a79d
-commit 3b9798bda15bd3f598f5ef07595d64e23504da91
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 9 02:58:02 2018 +0000
+commit 90ef45f7aac33eaf55ec344e101548a01e570f29
+Author: schwarze@openbsd.org <schwarze@openbsd.org>
+Date: Tue Nov 13 07:22:45 2018 +0000
- upstream: reorder child environment preparation so that variables
+ upstream: fix markup error (missing blank before delimiter); from
- read from ~/.ssh/environment (if enabled) do not override SSH_* variables set
- by the server.
+ Mike Frysinger <vapier at gentoo dot org>
- OpenBSD-Commit-ID: 59f9d4c213cdcef2ef21f4b4ae006594dcf2aa7a
+ OpenBSD-Commit-ID: 1bc5392f795ca86318d695e0947eaf71a5a4f6d9
-commit 0368889f82f63c82ff8db9f8c944d89e7c657db4
+commit 960e7c672dc106f3b759c081de3edb4d1138b36e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 8 03:35:36 2018 +0000
+Date: Fri Nov 9 02:57:58 2018 +0000
- upstream: fix incorrect expansion of %i in
+ upstream: typo in error message; caught by Debian lintian, via
- load_public_identity_files(); reported by Roumen Petrov
+ Colin Watson
- OpenBSD-Commit-ID: a827289e77149b5e0850d72a350c8b0300e7ef25
+ OpenBSD-Commit-ID: bff614c7bd1f4ca491a84e9b5999f848d0d66758
-commit 027607fc2db6a0475a3380f8d95c635482714cb0
+commit 81f1620c836e6c79c0823ba44acca605226a80f1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 8 01:55:40 2018 +0000
+Date: Fri Nov 9 02:56:22 2018 +0000
- upstream: fix some over-long lines and __func__ up some debug
+ upstream: correct local variable name; from yawang AT microsoft.com
- messages
+ OpenBSD-Commit-ID: a0c228390856a215bb66319c89cb3959d3af8c87
+
+commit 1293740e800fa2e5ccd38842a2e4970c6f3b9831
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Oct 31 11:20:05 2018 +0000
+
+ upstream: Import new moduli.
- OpenBSD-Commit-ID: c70a60b4c8207d9f242fc2351941ba50916bb267
+ OpenBSD-Commit-ID: c07772f58028fda683ee6abd41c73da3ff70d403
-commit 6ff6fda705bc204456a5fa12518dde6e8790bb02
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Thu Jun 7 11:26:14 2018 +0000
+commit 46925ae28e53fc9add336a4fcdb7ed4b86c3591c
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Oct 26 01:23:03 2018 +0000
- upstream: tweak previous;
+ upstream: mention ssh-ed25519-cert-v01@openssh.com in list of cert
- OpenBSD-Commit-ID: f98f16af10b28e24bcecb806cb71ea994b648fd6
+ key type at start of doc
+
+ OpenBSD-Commit-ID: b46b0149256d67f05f2d5d01e160634ed1a67324
-commit f2c06ab8dd90582030991f631a2715216bf45e5a
+commit 8d8340e2c215155637fe19cb1a837f71b2d55f7b
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jun 8 17:43:36 2018 +1000
+Date: Fri Nov 16 13:32:13 2018 +1100
- Remove ability to override $LD.
+ Remove fallback check for /usr/local/ssl.
- Since autoconf always uses $CC to link C programs, allowing users to
- override LD caused mismatches between what LD_LINK_IFELSE thought worked
- and what ld thought worked. If you do need to do this kind of thing you
- need to set a compiler flag such as gcc's -fuse-ld in LDFLAGS.
+ If configure could not find a working OpenSSL installation it would
+ fall back to checking in /usr/local/ssl. This made sense back when
+ systems did not ship with OpenSSL, but most do and OpenSSL 1.1 doesn't
+ use that as a default any more. The fallback behaviour also meant
+ that if you pointed --with-ssl-dir at a specific directory and it
+ didn't work, it would silently use either the system libs or the ones
+ in /usr/local/ssl. If you want to use /usr/local/ssl you'll need to
+ pass configure --with-ssl-dir=/usr/local/ssl. ok djm@
-commit e1542a80797b4ea40a91d2896efdcc76a57056d2
+commit ce93472134fb22eff73edbcd173a21ae38889331
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Jun 8 13:55:59 2018 +1000
+Date: Fri Nov 16 12:44:01 2018 +1100
- Better detection of unsupported compiler options.
+ Fix check for OpenSSL 1.0.1 exactly.
- Should prevent "unsupported -Wl,-z,retpoline" warnings during linking.
- ok djm@
+ Both INSTALL and configure.ac claim OpenSSL >= 1.0.1 is supported; fix
+ compile-time check for 1.0.1 to match.
-commit 57379dbd013ad32ee3f9989bf5f5741065428360
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 7 14:29:43 2018 +0000
+commit f2970868f86161a22b2c377057fa3891863a692a
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Nov 11 15:58:20 2018 +1100
- upstream: test the correct configuration option name
+ Improve warnings in cygwin service setup.
- OpenBSD-Regress-ID: 492279ea9f65657f97a970e0e7c7fd0b339fee23
+ bz#2922, patch from vinschen at redhat.com.
-commit 6d41815e202fbd6182c79780b6cc90e1ec1c9981
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 7 09:26:42 2018 +0000
+commit bd2d54fc1eee84bf87158a1277a50e6c8a303339
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Nov 11 15:54:54 2018 +1100
- upstream: some permitlisten fixes from markus@ that I missed in my
-
- insomnia-fueled commits last night
+ Remove hardcoded service name in cygwin setup.
- OpenBSD-Commit-ID: 26f23622e928996086e85b1419cc1c0f136e359c
+ bz#2922, patch from Christian.Lupien at USherbrooke.ca, sanity check
+ by vinschen at redhat.com.
-commit 4319f7a868d86d435fa07112fcb6153895d03a7f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 7 04:46:34 2018 +0000
+commit d0153c77bf7964e694f1d26c56c41a571b8e9466
+Author: Dag-Erling Smørgrav <des@des.no>
+Date: Tue Oct 9 23:03:40 2018 +0200
- upstream: permitlisten/PermitListen unit test from Markus
-
- OpenBSD-Regress-ID: ab12eb42f0e14926980441cf7c058a6d1d832ea5
+ AC_CHECK_SIZEOF() no longer needs a second argument.
-commit fa09076410ffc2d34d454145af23c790d728921e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 7 04:31:51 2018 +0000
+commit 9b47b083ca9d866249ada9f02dbd57c87b13806e
+Author: Manoj Ampalam <manojamp@microsoft.com>
+Date: Thu Nov 8 22:41:59 2018 -0800
- upstream: fix regression caused by recent permitlisten option commit:
-
- authorized_keys lines that contained permitopen/permitlisten were being
- treated as invalid.
+ Fix error message w/out nistp521.
- OpenBSD-Commit-ID: 7ef41d63a5a477b405d142dc925b67d9e7aaa31b
+ Correct error message when OpenSSL doesn't support certain ECDSA key
+ lengths.
-commit 7f90635216851f6cb4bf3999e98b825f85d604f8
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jun 6 18:29:18 2018 +0000
+commit 624d19ac2d56fa86a22417c35536caceb3be346f
+Author: Eneas U de Queiroz <cote2004-github@yahoo.com>
+Date: Tue Oct 9 16:17:42 2018 -0300
- upstream: switch config file parsing to getline(3) as this avoids
+ fix compilation with openssl built without ECC
- static limits noted by gerhard@; ok dtucker@, djm@
+ ECDSA code in openssh-compat.h and libressl-api-compat.c needs to be
+ guarded by OPENSSL_HAS_ECC
- OpenBSD-Commit-ID: 6d702eabef0fa12e5a1d75c334a8c8b325298b5c
+ Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
-commit 392db2bc83215986a91c0b65feb0e40e7619ce7e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 6 18:25:33 2018 +0000
+commit 1801cd11d99d05a66ab5248c0555f55909a355ce
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Nov 8 15:03:11 2018 +1100
- upstream: regress test for PermitOpen
+ Simplify OpenSSL 1.1 function checks.
- OpenBSD-Regress-ID: ce8b5f28fc039f09bb297fc4a92319e65982ddaf
+ Replace AC_SEARCH_LIBS checks for OpenSSL 1.1 functions with a single
+ AC_CHECK_FUNCS. ok djm@
-commit 803d896ef30758135e2f438bdd1a0be27989e018
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 6 18:24:15 2018 +0000
+commit bc32f118d484e4d71d2a0828fd4eab7e4176c9af
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Nov 5 17:31:24 2018 +1100
- upstream: man bits for permitlisten authorized_keys option
+ Fix pasto for HAVE_EVP_CIPHER_CTX_SET_IV.
- OpenBSD-Commit-ID: 86910af8f781a4ac5980fea125442eb25466dd78
+ Prevents unnecessary redefinition. Patch from mforney at mforney.org.
-commit 04df43208b5b460d7360e1598f876b92a32f5922
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 6 18:24:00 2018 +0000
+commit 3719df60c66abc4b47200d41f571d67772f293ba
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Wed Oct 31 22:21:03 2018 +1100
- upstream: man bits for PermitListen
-
- OpenBSD-Commit-ID: 35b200cba4e46a16a4db6a80ef11838ab0fad67c
+ Import new moduli.
-commit 93c06ab6b77514e0447fe4f1d822afcbb2a9be08
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 6 18:23:32 2018 +0000
+commit 595605d4abede475339d6a1f07a8cc674c11d1c3
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Oct 28 15:18:13 2018 +1100
- upstream: permitlisten option for authorized_keys; ok markus@
-
- OpenBSD-Commit-ID: 8650883018d7aa893173d703379e4456a222c672
+ Update check for minimum OpenSSL version.
-commit 115063a6647007286cc8ca70abfd2a7585f26ccc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 6 18:22:41 2018 +0000
+commit 6ab75aba340d827140d7ba719787aabaf39a0355
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Oct 28 15:16:31 2018 +1100
- upstream: Add a PermitListen directive to control which server-side
-
- addresses may be listened on when the client requests remote forwarding (ssh
- -R).
-
- This is the converse of the existing PermitOpen directive and this
- includes some refactoring to share much of its implementation.
-
- feedback and ok markus@
-
- OpenBSD-Commit-ID: 15a931238c61a3f2ac74ea18a98c933e358e277f
+ Update required OpenSSL versions to match current.
-commit 7703ae5f5d42eb302ded51705166ff6e19c92892
+commit c801b0e38eae99427f37869370151b78f8e15c5d
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Jun 6 16:04:29 2018 +1000
+Date: Sun Oct 28 14:34:12 2018 +1100
- Use ssh-keygen -A to generate missing host keys.
+ Use detected version functions in openssl compat.
- Instead of testing for each specific key type, use ssh-keygen -A to
- generate any missing host key types.
+ Use detected functions in compat layer instead of guessing based on
+ versions. Really fixes builds with LibreSSL, not just configure.
-commit e8d59fef1098e24f408248dc64e5c8efa5d01f3c
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Jun 1 06:23:10 2018 +0000
+commit 262d81a259d4aa1507c709ec9d5caa21c7740722
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Oct 27 16:45:59 2018 +1100
- upstream: add missing punctuation after %i in ssh_config.5, and
+ Check for the existence of openssl version funcs.
- make the grammatical format in sshd_config.5 match that in ssh_config.5;
-
- OpenBSD-Commit-ID: e325663b9342f3d556e223e5306e0d5fa1a74fa0
+ Check for the existence of openssl version functions and use the ones
+ detected instead of trying to guess based on the int32 version
+ identifier. Fixes builds with LibreSSL.
-commit a1f737d6a99314e291a87856122cb4dbaf64c641
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Jun 1 05:52:26 2018 +0000
+commit 406a24b25d6a2bdd70cacd16de7e899dcb2a8829
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Oct 26 13:43:28 2018 +1100
- upstream: oops - further adjustment to text neccessary;
+ fix builds on OpenSSL <= 1.0.x
- OpenBSD-Commit-ID: 23585576c807743112ab956be0fb3c786bdef025
+ I thought OpenSSL 1.0.x offered the new-style OpenSSL_version_num() API
+ to obtain version number, but they don't.
-commit 294028493471e0bd0c7ffe55dc0c0a67cba6ec41
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Jun 1 05:50:18 2018 +0000
+commit 859754bdeb41373d372e36b5dc89c547453addb3
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Oct 23 17:10:41 2018 +1100
- upstream: %U needs to be escaped; tweak text;
+ remove remaining references to SSLeay
- OpenBSD-Commit-ID: 30887b73ece257273fb619ab6f4e86dc92ddc15e
+ Prompted by Rosen Penev
-commit e5019da3c5a31e6e729a565f2b886a80c4be96cc
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jun 1 04:31:48 2018 +0000
+commit b9fea45a68946c8dfeace72ad1f6657c18f2a98a
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Oct 23 17:10:35 2018 +1100
- upstream: Apply umask to all incoming files and directories not
-
- just files. This makes sure it gets applied to directories too, and prevents
- a race where files get chmodded after creation. bz#2839, ok djm@
-
- OpenBSD-Commit-ID: 3168ee6c7c39093adac4fd71039600cfa296203b
+ regen depend
-commit a1dcafc41c376332493b9385ee39f9754dc145ec
+commit a65784c9f9c5d00cf1a0e235090170abc8d07c73
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 1 03:52:37 2018 +0000
+Date: Tue Oct 23 05:56:35 2018 +0000
- upstream: Adapt to extra default verboisity from ssh-keygen when
+ upstream: refer to OpenSSL not SSLeay;
- searching for and hashing known_hosts entries in a single operation
- (ssh-keygen -HF ...) Patch from Anton Kremenetsky
+ we're old, but we don't have to act it
- OpenBSD-Regress-ID: 519585a4de35c4611285bd6a7272766c229b19dd
+ OpenBSD-Commit-ID: 9ca38d11f8ed19e61a55108d1e892d696cee08ec
-commit 76f314c75dffd4a55839d50ee23622edad52c168
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue May 22 00:22:49 2018 +0000
+commit c0a35265907533be10ca151ac797f34ae0d68969
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Oct 22 11:22:50 2018 +1100
- upstream: Add TEST_SSH_FAIL_FATAL variable, to force all failures
+ fix compile for openssl 1.0.x w/ --with-ssl-engine
- to instantly abort the test. Useful in capturing clean logs for individual
- failure cases.
-
- OpenBSD-Regress-ID: feba18cf338c2328b9601bd4093cabdd9baa3af1
+ bz#2921, patch from cotequeiroz
-commit 065c8c055df8d83ae7c92e5e524a579d87668aab
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri May 11 03:51:06 2018 +0000
+commit 31b49525168245abe16ad49d7b7f519786b53a38
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Oct 22 20:05:18 2018 +1100
- upstream: Clean up comment.
+ Include openssl compatibility.
- OpenBSD-Regress-ID: 6adb35f384d447e7dcb9f170d4f0d546d3973e10
+ Patch from rosenp at gmail.com via openssh-unix-dev.
-commit 01b048c8eba3b021701bd0ab26257fc82903cba8
+commit a4fc253f5f44f0e4c47aafe2a17d2c46481d3c04
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 1 04:21:29 2018 +0000
+Date: Fri Oct 19 03:12:42 2018 +0000
- upstream: whitespace
+ upstream: when printing certificate contents "ssh-keygen -Lf
- OpenBSD-Commit-ID: e5edb5e843ddc9b73a8e46518899be41d5709add
+ /path/certificate", include the algorithm that the CA used to sign the cert.
+
+ OpenBSD-Commit-ID: 1ea20b5048a851a7a0758dcb9777a211a2c0dddd
-commit 854ae209f992465a276de0b5f10ef770510c2418
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 1 04:05:29 2018 +0000
+commit 83b3d99d2b47321b7ebb8db6f6ea04f3808bc069
+Author: florian@openbsd.org <florian@openbsd.org>
+Date: Mon Oct 15 11:28:50 2018 +0000
- upstream: make ssh_remote_ipaddr() capable of being called after
+ upstream: struct sockaddr_storage is guaranteed to be large enough,
- the ssh->state has been torn down; bz#2773
+ no need to check the size. OK kn, deraadt
- OpenBSD-Commit-ID: 167f12523613ca3d16d7716a690e7afa307dc7eb
+ OpenBSD-Commit-ID: 0aa56e92eb49c79f495b31a5093109ec5841f439
-commit 3e088aaf236ef35beeef3c9be93fd53700df5861
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 1 03:51:34 2018 +0000
+commit aede1c34243a6f7feae2fb2cb686ade5f9be6f3d
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 17 11:01:20 2018 +1100
- upstream: return correct exit code when searching for and hashing
+ Require OpenSSL 1.1.x series 1.1.0g or greater
- known_hosts entries in a single operation (ssh-keygen -HF hostname); bz2772
- Report and fix from Anton Kremenetsky
+ Previous versions have a bug with EVP_CipherInit() when passed a
+ NULL EVP_CIPHER, per https://github.com/openssl/openssl/pull/4613
- OpenBSD-Commit-ID: ac10ca13eb9bb0bc50fcd42ad11c56c317437b58
+ ok dtucker@
-commit 9c935dd9bf05628826ad2495d3e8bdf3d3271c21
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 1 03:33:53 2018 +0000
+commit 08300c211409c212e010fe2e2f2883e573a04ce2
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 17 08:12:02 2018 +1100
- upstream: make UID available as a %-expansion everywhere that the
-
- username is available currently. In the client this is via %i, in the server
- %U (since %i was already used in the client in some places for this, but used
- for something different in the server); bz#2870, ok dtucker@
+ unbreak compilation with --with-ssl-engine
- OpenBSD-Commit-ID: c7e912b0213713316cb55db194b3a6415b3d4b95
+ Missing last argument to OPENSSL_init_crypto()
-commit d8748b91d1d6c108c0c260ed41fa55f37b9ef34b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 1 03:11:49 2018 +0000
+commit 1673274aee67ce0eb6f00578b6f3d2bcbd58f937
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Oct 16 14:45:57 2018 +1100
- upstream: prefer argv0 to "ssh" when re-executing ssh for ProxyJump
-
- directive; bz2831, feedback and ok dtucker@
+ Remove gcc spectre mitigation flags.
- OpenBSD-Commit-ID: 3cec709a131499fbb0c1ea8a0a9e0b0915ce769e
+ Current impementions of the gcc spectre mitigation flags cause
+ miscompilations when combined with other flags and do not provide much
+ protection. Found by fweimer at redhat.com, ok djm@
-commit fbb4b5fd4f8e0bb89732670a01954e18b69e15ba
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri May 25 07:11:01 2018 +0000
+commit 4e23deefd7959ef83c73ed9cce574423438f6133
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Oct 16 10:51:52 2018 +1100
- upstream: Do not ban PTY allocation when a sshd session is restricted
-
- because the user password is expired as it breaks password change dialog.
-
- regression in openssh-7.7 reported by Daniel Wagner
+ Avoid deprecated OPENSSL_config when using 1.1.x
- OpenBSD-Commit-ID: 9fc09c584c6f1964b00595e3abe7f83db4d90d73
+ OpenSSL 1.1.x soft-deprecated OPENSSL_config in favour of
+ OPENSSL_init_crypto; pointed out by Jakub Jelen
-commit f6a59a22b0c157c4c4e5fd7232f868138223be64
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri May 25 04:25:46 2018 +0000
+commit 797cdd9c8468ed1125ce60d590ae3f1397866af4
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Oct 12 16:58:47 2018 +1100
- upstream: Fix return value confusion in several functions (readdir,
-
- download and fsync). These should return -1 on error, not a sftp status code.
-
- patch from Petr Cerny in bz#2871
+ Don't avoid our *sprintf replacements.
- OpenBSD-Commit-ID: 651aa0220ad23c9167d9297a436162d741f97a09
+ Don't let systems with broken printf(3) avoid our replacements
+ via asprintf(3)/vasprintf(3) calling libc internally. From djm@
-commit 1da5934b860ac0378d52d3035b22b6670f6a967e
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri May 25 03:20:59 2018 +0000
+commit e526127cbd2f8ad88fb41229df0c9b850c722830
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Oct 12 16:43:35 2018 +1100
- upstream: If select() fails in ssh_packet_read_seqnr go directly to
-
- the error path instead of trying to read from the socket on the way out,
- which resets errno and causes the true error to be misreported. ok djm@
+ Check if snprintf understands %zu.
- OpenBSD-Commit-ID: 2614edaadbd05a957aa977728aa7a030af7c6f0a
+ If the platforms snprintf and friends don't understand %zu, use the
+ compat replacement. Prevents segfaults on those platforms.
-commit 4ef75926ef517d539f2c7aac3188b09f315c86a7
+commit cf39f875191708c5f2f1a3c1c9019f106e74aea3
Author: Damien Miller <djm@mindrot.org>
-Date: Fri May 25 13:36:58 2018 +1000
-
- Permit getuid()/geteuid() syscalls.
-
- Requested for Linux/s390; patch from Eduardo Barretto via bz#2752;
- ok dtucker
-
-commit 4b22fd8ecefd059a66140be67f352eb6145a9d88
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue May 22 00:13:26 2018 +0000
+Date: Fri Oct 12 09:48:05 2018 +1100
- upstream: support ProxyJump=none to disable ProxyJump
-
- functionality; bz#2869 ok dtucker@
-
- OpenBSD-Commit-ID: 1c06ee08eb78451b5837fcfd8cbebc5ff3a67a01
+ remove stale link, tweak
-commit f41bcd70f55b4f0fc4d8e1039cb361ac922b23fb
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 15 05:40:11 2018 +0000
+commit a7205e68decf7de2005810853b4ce6b222b65e2a
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Oct 12 09:47:20 2018 +1100
- upstream: correct keyowrd name (permitemptypasswords); from brendan
-
- macdonell
-
- OpenBSD-Commit-ID: ef1bdbc936b2ea693ee37a4c20a94d4d43f5fda3
+ update version numbers ahead of release
-commit f18bc97151340127859634d20d79fd39ec8a7f39
+commit 1a4a9cf80f5b92b9d1dadd0bfa8867c04d195391
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri May 11 04:01:11 2018 +0000
+Date: Thu Oct 11 03:48:04 2018 +0000
- upstream: Emphasise that -w implicitly sets Tunnel=point-to-point
+ upstream: don't send new-style rsa-sha2-*-cert-v01@openssh.com names to
- and that users should specify an explicit Tunnel directive if they don't want
- this. bz#2365.
+ older OpenSSH that can't handle them. spotted by Adam Eijdenberg; ok dtucker
- OpenBSD-Commit-ID: 1a8d9c67ae213ead180481900dbbb3e04864560d
+ OpenBSD-Commit-ID: 662bbc402e3d7c9b6c322806269698106a6ae631
-commit 32e4e94e1511fe0020fbfbb62399d31b2d22a801
+commit dc8ddcdf1a95e011c263486c25869bb5bf4e30ec
Author: Damien Miller <djm@mindrot.org>
-Date: Mon May 14 14:40:08 2018 +1000
+Date: Thu Oct 11 13:08:59 2018 +1100
- sync fmt_scaled.c
-
- revision 1.17
- date: 2018/05/14 04:39:04; author: djm; state: Exp; lines: +5 -2;
- commitid: 53zY8GjViUBnWo8Z;
- constrain fractional part to [0-9] (less confusing to static analysis); ok ian@
+ update depends
-commit 54268d589e85ecc43d3eba8d83f327bdada9d696
+commit 26841ac265603fd2253e6832e03602823dbb4022
Author: Damien Miller <djm@mindrot.org>
-Date: Fri May 11 14:04:40 2018 +1000
+Date: Thu Oct 11 13:02:11 2018 +1100
- fix key-options.sh on platforms without openpty(3)
-
- Skip the pty tests if the platform lacks openpty(3) and has to chown(2)
- the pty device explicitly. This typically requires root permissions that
- this test lacks.
+ some more duplicated key algorithm lines
- bz#2856 ok dtucker@
+ From Adam Eijdenberg
-commit b2140a739be4c3b43cc1dc08322dca39a1e39d20
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri May 11 03:38:51 2018 +0000
+commit 5d9d17603bfbb620195a4581025052832b4c4adc
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Oct 11 11:56:36 2018 +1100
- upstream: implement EMFILE mitigation for ssh-agent: remember the
-
- fd rlimit and stop accepting new connections when it is exceeded (with some
- grace). Accept is resumed when enough connections are closed.
-
- bz#2576. feedback deraadt; ok dtucker@
+ fix duplicated algorithm specification lines
- OpenBSD-Commit-ID: 6a85d9cec7b85741961e7116a49f8dae777911ea
+ Spotted by Adam Eijdenberg
-commit fdba503fdfc647ee8a244002f1581e869c1f3d90
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri May 11 03:22:55 2018 +0000
+commit ebfafd9c7a5b2a7fb515ee95dbe0e44e11d0a663
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Oct 11 00:52:46 2018 +0000
- upstream: Explicit cast when snprintf'ing an uint64. Prevents
+ upstream: typo in plain RSA algorithm counterpart names for
- warnings on platforms where int64 is long not long long. ok djm@
+ certificates; spotted by Adam Eijdenberg; ok dtucker@
- OpenBSD-Commit-ID: 9c5359e2fbfce11dea2d93f7bc257e84419bd001
+ OpenBSD-Commit-ID: bfcdeb6f4fc9e7607f5096574c8f118f2e709e00
-commit e7751aa4094d51a9bc00778aa8d07e22934c55ee
-Author: bluhm@openbsd.org <bluhm@openbsd.org>
-Date: Thu Apr 26 14:47:03 2018 +0000
+commit c29b111e7d87c2324ff71c80653dd8da168c13b9
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Oct 11 11:29:35 2018 +1100
- upstream: Since the previous commit, ssh regress test sftp-chroot was
+ check pw_passwd != NULL here too
- failing. The sftp program terminated with the wrong exit code as sftp called
- fatal() instad of exit(0). So when the sigchld handler waits for the child,
- remember that it was found. Then don't expect that main() can wait again. OK
- dtucker@
+ Again, for systems with broken NIS implementations.
- OpenBSD-Commit-ID: bfafd940c0de5297940c71ddf362053db0232266
+ Prompted by coolbugcheckers AT gmail.com
-commit 7c15301841e2e9d37cae732400de63ae9c0961d6
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Apr 29 17:54:12 2018 +1000
+commit fe8e8f349a553ef4c567acd418aac769a82b7729
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Oct 11 11:03:15 2018 +1100
- Use includes.h instead of config.h.
+ check for NULL return from shadow_pw()
- This ensures it picks up the definition of DEF_WEAK, the lack of which
- can cause compile errors in some cases (eg modern AIX). From
- michael at felt.demon.nl.
+ probably unreachable on this platform; pointed out by
+ coolbugcheckers AT gmail.com
-commit cec338967a666b7c8ad8b88175f2faeddf268116
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Apr 19 09:53:14 2018 +1000
+commit acc59cbe7a1fb169e1c3caba65a39bd74d6e030d
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Wed Oct 10 16:43:49 2018 +0000
- Omit 3des-cbc if OpenSSL built without DES.
+ upstream: introducing openssh 7.9
- Patch from hongxu.jia at windriver.com, ok djm@
+ OpenBSD-Commit-ID: 42d526a9fe01a40dd299ac58014d3349adf40e25
-commit a575ddd58835759393d2dddd16ebe5abdb56485e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Apr 16 22:50:44 2018 +0000
+commit 12731158c75c8760a8bea06350eeb3e763fe1a07
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Oct 11 10:29:29 2018 +1100
- upstream: Disable SSH2_MSG_DEBUG messages for Twisted Conch clients
+ supply callback to PEM_read_bio_PrivateKey
- without version numbers since they choke on them under some circumstances.
- https://twistedmatrix.com/trac/ticket/9422 via Colin Watson
+ OpenSSL 1.1.0i has changed the behaviour of their PEM APIs,
+ so that empty passphrases are interpreted differently. This
+ probabalistically breaks loading some keys, because the PEM format
+ is terrible and doesn't include a proper MAC.
- Newer Conch versions have a version number in their ident string and
- handle debug messages okay. https://twistedmatrix.com/trac/ticket/9424
+ Avoid this by providing a basic callback to avoid passing empty
+ passphrases to OpenSSL in cases where one is required.
- OpenBSD-Commit-ID: 6cf7be262af0419c58ddae11324d9c0dc1577539
+ Based on patch from Jakub Jelen in bz#2913; ok dtucker@
-commit 390c7000a8946db565b66eab9e52fb11948711fa
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Apr 14 21:50:41 2018 +0000
+commit d1d301a1dd5d6cc3a9ed93ab7ab09dda4cb456e0
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 10 14:57:00 2018 +1100
- upstream: don't free the %C expansion, it's used later for
+ in pick_salt() avoid dereference of NULL passwords
- LocalCommand
+ Apparently some NIS implementations can leave pw->pw_passwd (or the
+ shadow equivalent) NULL.
- OpenBSD-Commit-ID: 857b5cb37b2d856bfdfce61289a415257a487fb1
+ bz#2909; based on patch from Todd Eigenschink
-commit 3455f1e7c48e2e549192998d330214975b9b1dc7
+commit edbb6febccee084d212fdc0cb05b40cb1c646ab1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Apr 13 05:04:12 2018 +0000
+Date: Tue Oct 9 05:42:23 2018 +0000
- upstream: notify user immediately when underlying ssh process dies;
+ upstream: Treat all PEM_read_bio_PrivateKey() errors when a passphrase
- patch from Thomas Kuthan in bz2719; ok dtucker@
+ is specified as "incorrect passphrase" instead of trying to choose between
+ that and "invalid format".
- OpenBSD-Commit-ID: 78fac88c2f08054d1fc5162c43c24162b131cf78
-
-commit 1c5b4bc827f4abc3e65888cda061ad5edf1b8c7c
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Apr 13 16:23:57 2018 +1000
+ libcrypto can return ASN1 parsing errors rather than the expected
+ decrypt error in certain infrequent cases when trying to decrypt/parse
+ PEM private keys when supplied with an invalid passphrase.
+
+ Report and repro recipe from Thomas Deutschmann in bz#2901
+
+ ok markus@
+
+ OpenBSD-Commit-ID: b1d4cd92395f9743f81c0d23aab2524109580870
- Allow nanosleep in preauth privsep child.
+commit 2581333d564d8697837729b3d07d45738eaf5a54
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Fri Oct 5 14:26:09 2018 +0000
+
+ upstream: Support using service names for port numbers.
- The new timing attack mitigation code uses nanosleep in the preauth
- codepath, allow in systrace andbox too.
+ * Try to resolve a port specification with getservbyname(3) if a
+ numeric conversion fails.
+ * Make the "Port" option in ssh_config handle its argument as a
+ port rather than a plain integer.
+
+ ok dtucker@ deraadt@
+
+ OpenBSD-Commit-ID: e7f03633133205ab3dfbc67f9df7475fabae660d
-commit 0e73428038d5ecfa5d2a28cff26661502a7aff4e
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Apr 13 16:06:29 2018 +1000
+commit e0d6501e86734c48c8c503f81e1c0926e98c5c4c
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Oct 4 07:47:35 2018 +0000
- Allow nanosleep in preauth privsep child.
+ upstream: when the peer sends a channel-close message, make sure we
- The new timing attack mitigation code uses nanosleep in the preauth
- codepath, allow in sandbox.
+ close the local extended read fd (stderr) along with the regular read fd
+ (stdout). Avoids weird stuck processed in multiplexing mode.
+
+ Report and analysis by Nelson Elhage and Geoffrey Thomas in bz#2863
+
+ ok dtucker@ markus@
+
+ OpenBSD-Commit-ID: a48a2467fe938de4de69d2e7193d5fa701f12ae9
-commit e9d910b0289c820852f7afa67f584cef1c05fe95
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Apr 13 03:57:26 2018 +0000
+commit 6f1aabb128246f445e33b8844fad3de9cb1d18cb
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Oct 4 01:04:52 2018 +0000
- upstream: Defend against user enumeration timing attacks. This
+ upstream: factor out channel status formatting from
- establishes a minimum time for each failed authentication attempt (5ms) and
- adds a per-user constant derived from a host secret (0-4ms). Based on work
- by joona.kannisto at tut.fi, ok markus@ djm@.
+ channel_open_message() so we can use it in other debug messages
- OpenBSD-Commit-ID: b7845b355bb7381703339c8fb0e57e81a20ae5ca
+ OpenBSD-Commit-ID: 9c3903ca28fcabad57f566c9d0045b41ab7d52ba
-commit d97874cbd909eb706886cd0cdd418f812c119ef9
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Apr 13 13:43:55 2018 +1000
+commit f1dd179e122bdfdb7ca3072d9603607740efda05
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Oct 4 00:10:11 2018 +0000
- Using "==" in shell tests is not portable.
+ upstream: include a little more information about the status and
- Patch from rsbecker at nexbridge.com.
+ disposition of channel's extended (stderr) fd; makes debugging some things a
+ bit easier. No behaviour change.
+
+ OpenBSD-Commit-ID: 483eb6467dc7d5dbca8eb109c453e7a43075f7ce
-commit cfb1d9bc76734681e3dea532a1504fcd466fbe91
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Apr 13 13:38:06 2018 +1000
+commit 2d1428b11c8b6f616f070f2ecedce12328526944
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Oct 4 00:04:41 2018 +0000
- Fix tunnel forwarding broken in 7.7p1
+ upstream: explicit_bzero here to be consistent with other kex*.c;
- bz2855, ok dtucker@
+ report from coolbugcheckers AT gmail.com
+
+ OpenBSD-Commit-ID: a90f146c5b5f5b1408700395e394f70b440856cb
-commit afa6e79b76fb52a0c09a29688b5c0d125eb08302
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Apr 13 13:31:42 2018 +1000
+commit 5eff5b858e717e901e6af6596306a114de9f79f2
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 3 06:38:35 2018 +0000
- prefer to use getrandom() for PRNG seeding
+ upstream: Allow ssh_config IdentityAgent directive to accept
- Only applies when built --without-openssl. Thanks Jann Horn for
- reminder.
+ environment variable names as well as explicit paths. ok dtucker@
+
+ OpenBSD-Commit-ID: 2f0996e103876c53d8c9dd51dcce9889d700767b
-commit 575fac34a97f69bc217b235f81de9f8f433eceed
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Apr 13 13:13:33 2018 +1000
+commit a46ac4d86b25414d78b632e8173578b37e5f8a83
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Oct 2 12:51:58 2018 +0000
- Revert $REGRESSTMP changes.
+ upstream: mention INFO@openssh.com for sending SIGINFO
- Revert 3fd2d229 and subsequent changes as they turned out to be a
- portability hassle.
+ OpenBSD-Commit-ID: 132471eeb0df658210afd27852fe65131b26e900
-commit 10479cc2a4acd6faaf643eb305233b49d70c31c1
+commit ff3a411cae0b484274b7900ef52ff4dad3e12876
Author: Damien Miller <djm@mindrot.org>
-Date: Tue Apr 10 10:19:02 2018 +1000
+Date: Tue Oct 2 22:49:40 2018 +1000
- Many typo fixes from Karsten Weiss
-
- Spotted using https://github.com/lucasdemarchi/codespell
+ only support SIGINFO on systems with SIGINFO
-commit 907da2f88519b34189fd03fac96de0c52d448233
+commit cd98925c6405e972dc9f211afc7e75e838abe81c
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Apr 10 00:14:10 2018 +0000
+Date: Tue Oct 2 12:40:07 2018 +0000
- upstream: more typos spotted by Karsten Weiss using codespell
+ upstream: Add server support for signalling sessions via the SSH
- OpenBSD-Regress-ID: d906a2aea0663810a658b7d0bc61a1d2907d4d69
+ channel/ session protocol. Signalling is only supported to sesssions that are
+ not subsystems and were not started with a forced command.
+
+ Long requested in bz#1424
+
+ Based on a patch from markus@ and reworked by dtucker@;
+ ok markus@ dtucker@
+
+ OpenBSD-Commit-ID: 4bea826f575862eaac569c4bedd1056a268be1c3
-commit 37e5f4a7ab9a8026e5fc2f47dafb0f1b123d39e9
+commit dba50258333f2604a87848762af07ba2cc40407a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Apr 10 00:13:27 2018 +0000
+Date: Wed Sep 26 07:32:44 2018 +0000
- upstream: make this a bit more portable-friendly
+ upstream: remove big ugly TODO comment from start of file. Some of
- OpenBSD-Regress-ID: 62f7b9e055e8dfaab92b3825f158beeb4ca3f963
+ the mentioned tasks are obsolete and, of the remainder, most are already
+ captured in PROTOCOL.mux where they better belong
+
+ OpenBSD-Commit-ID: 16d9d76dee42a5bb651c9d6740f7f0ef68aeb407
-commit 001aa55484852370488786bd40e9fdad4b465811
+commit 92b61a38ee9b765f5049f03cd1143e13f3878905
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Apr 10 00:10:49 2018 +0000
+Date: Wed Sep 26 07:30:05 2018 +0000
- upstream: lots of typos in comments/docs. Patch from Karsten Weiss
+ upstream: Document mux proxy mode; added by Markus in openssh-7.4
- after checking with codespell tool
- (https://github.com/lucasdemarchi/codespell)
+ Also add a little bit of information about the overall packet format
- OpenBSD-Commit-ID: 373222f12d7ab606598a2d36840c60be93568528
+ OpenBSD-Commit-ID: bdb6f6ea8580ef96792e270cae7857786ad84a95
-commit 260ede2787fe80b18b8d5920455b4fb268519c7d
+commit 9d883a1ce4f89b175fd77405ff32674620703fb2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Apr 9 23:54:49 2018 +0000
+Date: Wed Sep 26 01:48:57 2018 +0000
- upstream: don't kill ssh-agent's listening socket entriely if we
+ upstream: s/process_mux_master/mux_master_process/ in mux master
- fail to accept a connection; bz#2837, patch from Lukas Kuster
+ function names,
- OpenBSD-Commit-ID: 52413f5069179bebf30d38f524afe1a2133c738f
-
-commit ebc8b4656f9b0f834a642a9fb3c9fbca86a61838
-Author: tj@openbsd.org <tj@openbsd.org>
-Date: Mon Apr 9 20:41:22 2018 +0000
-
- upstream: the UseLogin option was removed, so remove it here too.
+ Gives better symmetry with the existing mux_client_*() names and makes
+ it more obvious when a message comes from the master vs client (they
+ are interleved in ControlMaster=auto mode).
- ok dtucker
+ no functional change beyond prefixing a could of log messages with
+ __func__ where they were previously lacking.
- OpenBSD-Commit-ID: 7080be73a64d68e21f22f5408a67a0ba8b1b6b06
+ OpenBSD-Commit-ID: b01f7c3fdf92692e1713a822a89dc499333daf75
-commit 3e36f281851fc8e9c996b33f108b2ae167314fbe
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sun Apr 8 07:36:02 2018 +0000
+commit c2fa53cd6462da82d3a851dc3a4a3f6b920337c8
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Sep 22 14:41:24 2018 +1000
- upstream: tweak previous;
-
- OpenBSD-Commit-ID: 2b9c23022ea7b9dddb62864de4e906000f9d7474
+ Remove unused variable in _ssh_compat_fflush.
-commit 8368571efd6693c5c57f850e23a2372acf3f865f
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Apr 7 13:50:10 2018 +0000
+commit d1b3540c21212624af907488960d703c7d987b42
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Sep 20 18:08:43 2018 +1000
- upstream: tweak previous;
-
- OpenBSD-Commit-ID: 38e347b6f8e888f5e0700d01abb1eba7caa154f9
+ Import updated moduli.
-commit 555294a7279914ae6795b71bedf4e6011b7636df
+commit b5e412a8993ad17b9e1141c78408df15d3d987e1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Apr 6 13:02:39 2018 +0000
+Date: Fri Sep 21 12:46:22 2018 +0000
- upstream: Allow "SendEnv -PATTERN" to clear environment variables
+ upstream: Allow ssh_config ForwardX11Timeout=0 to disable the
- previously labeled for sendind. bz#1285 ok dtucker@
+ timeout and allow X11 connections in untrusted mode indefinitely. ok dtucker@
- OpenBSD-Commit-ID: f6fec9e3d0f366f15903094fbe1754cb359a0df9
+ OpenBSD-Commit-ID: ea1ceed3f540b48e5803f933e59a03b20db10c69
-commit 40f5f03544a07ebd2003b443d42e85cb51d94d59
+commit cb24d9fcc901429d77211f274031653476864ec6
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Apr 6 04:15:45 2018 +0000
+Date: Fri Sep 21 12:23:17 2018 +0000
- upstream: relax checking of authorized_keys environment="..."
+ upstream: when compiled with GSSAPI support, cache supported method
- options to allow underscores in variable names (regression introduced in
- 7.7). bz2851, ok deraadt@
+ OIDs by calling ssh_gssapi_prepare_supported_oids() regardless of whether
+ GSSAPI authentication is enabled in the main config.
- OpenBSD-Commit-ID: 69690ffe0c97ff393f2c76d25b4b3d2ed4e4ac9c
-
-commit 30fd7f9af0f553aaa2eeda5a1f53f26cfc222b5e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Apr 6 03:51:27 2018 +0000
-
- upstream: add a couple of missed options to the config dump; patch
+ This avoids sandbox violations for configurations that enable GSSAPI
+ auth later, e.g.
- from Jakub Jelen via bz2835
+ Match user djm
+ GSSAPIAuthentication yes
- OpenBSD-Commit-ID: 5970adadf6ef206bee0dddfc75d24c2019861446
+ bz#2107; ok dtucker@
+
+ OpenBSD-Commit-ID: a5dd42d87c74e27cfb712b15b0f97ab20e0afd1d
-commit 8d6829be324452d2acd282d5f8ceb0adaa89a4de
+commit bbc8af72ba68da014d4de6e21a85eb5123384226
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Apr 6 03:34:27 2018 +0000
+Date: Fri Sep 21 12:20:12 2018 +0000
- upstream: ssh does not accept -oInclude=... on the commandline, the
+ upstream: In sshkey_in_file(), ignore keys that are considered for
- Include keyword is for configuration files only. bz#2840, patch from Jakub
- Jelen
+ being too short (i.e. SSH_ERR_KEY_LENGTH). These keys will not be considered
+ to be "in the file". This allows key revocation lists to contain short keys
+ without the entire revocation list being considered invalid.
- OpenBSD-Commit-ID: 32d052b4a7a7f22df35fe3f71c368c02b02cacb0
+ bz#2897; ok dtucker
+
+ OpenBSD-Commit-ID: d9f3d857d07194a42ad7e62889a74dc3f9d9924b
-commit 00c5222ddc0c8edcaa4ea45ac03befdc8013d137
+commit 383a33d160cefbfd1b40fef81f72eadbf9303a66
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Apr 5 22:54:28 2018 +0000
+Date: Fri Sep 21 03:11:36 2018 +0000
- upstream: We don't offer CBC cipher by default any more. Spotted by
+ upstream: Treat connections with ProxyJump specified the same as ones
- Renaud Allard (via otto@)
+ with a ProxyCommand set with regards to hostname canonicalisation (i.e. don't
+ try to canonicalise the hostname unless CanonicalizeHostname is set to
+ 'always').
- OpenBSD-Commit-ID: a559b1eef741557dd959ae378b665a2977d92dca
+ Patch from Sven Wegener via bz#2896
+
+ OpenBSD-Commit-ID: 527ff501cf98bf65fb4b29ed0cb847dda10f4d37
-commit 5ee8448ad7c306f05a9f56769f95336a8269f379
-Author: job@openbsd.org <job@openbsd.org>
-Date: Wed Apr 4 15:12:17 2018 +0000
+commit 0cbed248ed81584129b67c348dbb801660f25a6a
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Sep 20 23:40:16 2018 +0000
- upstream: Update default IPQoS in ssh(1), sshd(8) to DSCP AF21 for
-
- interactive and CS1 for bulk
-
- AF21 was selected as this is the highest priority within the low-latency
- service class (and it is higher than what we have today). SSH is elastic
- and time-sensitive data, where a user is waiting for a response via the
- network in order to continue with a task at hand. As such, these flows
- should be considered foreground traffic, with delays or drops to such
- traffic directly impacting user-productivity.
-
- For bulk SSH traffic, the CS1 "Lower Effort" marker was chosen to enable
- networks implementing a scavanger/lower-than-best effort class to
- discriminate scp(1) below normal activities, such as web surfing. In
- general this type of bulk SSH traffic is a background activity.
-
- An advantage of using "AF21" for interactive SSH and "CS1" for bulk SSH
- is that they are recognisable values on all common platforms (IANA
- https://www.iana.org/assignments/dscp-registry/dscp-registry.xml), and
- for AF21 specifically a definition of the intended behavior exists
- https://tools.ietf.org/html/rfc4594#section-4.7 in addition to the definition
- of the Assured Forwarding PHB group https://tools.ietf.org/html/rfc2597, and
- for CS1 (Lower Effort) there is https://tools.ietf.org/html/rfc3662
-
- The first three bits of "AF21" map to the equivalent IEEEE 802.1D PCP, IEEE
- 802.11e, MPLS EXP/CoS and IP Precedence value of 2 (also known as "Immediate",
- or "AC_BE"), and CS1's first 3 bits map to IEEEE 802.1D PCP, IEEE 802.11e,
- MPLS/CoS and IP Precedence value 1 ("Background" or "AC_BK").
+ upstream: actually make CASignatureAlgorithms available as a config
- OK deraadt@, "no objection" djm@
+ option
- OpenBSD-Commit-ID: d11d2a4484f461524ef0c20870523dfcdeb52181
+ OpenBSD-Commit-ID: 93fa7ff58314ed7b1ab7744090a6a91232e6ae52
-commit 424b544fbda963f973da80f884717c3e0a513288
+commit 62528870c0ec48cd86a37dd7320fb85886c3e6ee
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Apr 3 02:14:08 2018 +0000
+Date: Thu Sep 20 08:07:03 2018 +0000
- upstream: Import regenerated moduli file.
+ upstream: Import updated moduli.
- OpenBSD-Commit-ID: 1de0e85522051eb2ffa00437e1885e9d7b3e0c2e
+ OpenBSD-Commit-ID: 04431e8e7872f49a2129bf080a6b73c19d576d40
-commit 323f66ce934df2da551f256f37d69822428e1ca1
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Apr 6 04:18:35 2018 +0000
+commit e6933a2ffa0659d57f3c7b7c457b2c62b2a84613
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Thu Sep 20 06:58:48 2018 +0000
- upstream: Add test for username options parsing order, prompted by
+ upstream: reorder CASignatureAlgorithms, and add them to the
- bz#2849.
+ various -o lists; ok djm
- OpenBSD-Regress-ID: 6985cd32f38596882a3ac172ff8c510693b65283
+ OpenBSD-Commit-ID: ecb88baecc3c54988b4d1654446ea033da359288
-commit e8f474554e3bda102a797a2fbab0594ccc66f097
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Apr 6 14:11:44 2018 +1000
+commit aa083aa9624ea7b764d5a81c4c676719a1a3e42b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Sep 20 03:31:49 2018 +0000
- Expose SSH_AUTH_INFO_0 to PAM auth modules
+ upstream: fix "ssh -Q sig" to show correct signature algorithm list
- bz#2408, patch from Radoslaw Ejsmont; ok dtucker@
-
-commit 014ba209cf4c6a159baa30ecebbaddfa97da7100
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Apr 3 12:18:00 2018 +1000
-
- Import regenerated moduli file.
+ (it was erroneously showing certificate algorithms); prompted by markus@
+
+ OpenBSD-Commit-ID: 1cdee002f2f0c21456979deeb887fc889afb154d
-commit a0349a1cc4a18967ad1dbff5389bcdf9da098814
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Apr 2 15:38:28 2018 +1000
+commit ecac7e1f7add6b28874959a11f2238d149dc2c07
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Sep 20 03:30:44 2018 +0000
- update versions in .spec files
+ upstream: add CASignatureAlgorithms option for the client, allowing
+
+ it to specify which signature algorithms may be used by CAs when signing
+ certificates. Useful if you want to ban RSA/SHA1; ok markus@
+
+ OpenBSD-Commit-ID: 9159e5e9f67504829bf53ff222057307a6e3230f
-commit 816ad38f79792f5617e3913be306ddb27e91091c
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Apr 2 15:38:20 2018 +1000
+commit 86e5737c39153af134158f24d0cab5827cbd5852
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Sep 20 03:28:06 2018 +0000
- update version number
+ upstream: Add sshd_config CASignatureAlgorithms option to allow
+
+ control over which signature algorithms a CA may use when signing
+ certificates. In particular, this allows a sshd to ban certificates signed
+ with RSA/SHA1.
+
+ ok markus@
+
+ OpenBSD-Commit-ID: b05c86ef8b52b913ed48d54a9b9c1a7714d96bac
-commit 2c71ca1dd1efe458cb7dee3f8a1a566f913182c2
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Mar 30 18:23:07 2018 +1100
+commit f80e68ea7d62e2dfafc12f1a60ab544ae4033a0f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Sep 19 02:03:02 2018 +0000
- Disable native strndup and strnlen on AIX.
+ upstream: Make "ssh-add -q" do what it says on the tin: silence
- On at least some revisions of AIX, strndup returns unterminated strings
- under some conditions, apparently because strnlen returns incorrect
- values in those cases. Disable both on AIX and use the replacements
- from openbsd-compat. Fixes problem with ECDSA keys there, ok djm.
+ output from successful operations.
+
+ Based on patch from Thijs van Dijk; ok dtucker@ deraadt@
+
+ OpenBSD-Commit-ID: c4f754ecc055c10af166116ce7515104aa8522e1
-commit 6b5a17bc14e896e3904dc58d889b58934cfacd24
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Mar 26 13:12:44 2018 +1100
+commit 5e532320e9e51de720d5f3cc2596e95d29f6e98f
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Mon Sep 17 15:40:14 2018 +0000
- Include ssh_api.h for struct ssh.
+ upstream: When choosing a prime from the moduli file, avoid
- struct ssh is needed by implementations of sys_auth_passwd() that were
- converted in commit bba02a50. Needed to fix build on AIX, I assume for
- the other platforms too (although it should be harmless if not needed).
+ re-using the linenum variable for something that is not a line number to
+ avoid the confusion that resulted in the bug in rev. 1.64. This also lets us
+ pass the actual linenum to parse_prime() so the error messages include the
+ correct line number. OK markus@ some time ago.
+
+ OpenBSD-Commit-ID: 4d8e5d3e924d6e8eb70053e3defa23c151a00084
-commit bc3f80e4d191b8e48650045dfa8a682cd3aabd4d
+commit cce8cbe0ed7d1ba3a575310e0b63c193326ae616
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Mar 26 12:58:09 2018 +1100
+Date: Sat Sep 15 19:44:06 2018 +1000
- Remove UNICOS code missed during removal.
+ Fix openssl-1.1 fallout for --without-openssl.
- Fixes compile error on AIX.
+ ok djm@
-commit 9d57762c24882e2f000a21a0ffc8c5908a1fa738
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Sat Mar 24 19:29:03 2018 +0000
+commit 149519b9f201dac755f3cba4789f4d76fecf0ee1
+Author: Damien Miller <djm@mindrot.org>
+Date: Sat Sep 15 19:37:48 2018 +1000
- upstream: openssh-7.7
+ add futex(2) syscall to seccomp sandbox
- OpenBSD-Commit-ID: 274e614352460b9802c905f38fb5ea7ed5db3d41
+ Apparently needed for some glibc/openssl combinations.
+
+ Patch from Arkadiusz Miśkiewicz
-commit 4b7d8acdbbceef247dc035e611e577174ed8a87e
+commit 4488ae1a6940af704c4dbf70f55bf2f756a16536
Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 26 09:37:02 2018 +1100
+Date: Sat Sep 15 19:36:55 2018 +1000
- Remove authinfo.sh test dependency on printenv
-
- Some platforms lack printenv in the default $PATH.
- Reported by Tom G. Christensen
+ really add source for authopt_fuzz this time
-commit 4afeaf3dcb7dc70efd98fcfcb0ed28a6b40b820e
-Author: Tim Rice <tim@multitalents.net>
-Date: Sun Mar 25 10:00:21 2018 -0700
+commit 9201784b4a257c8345fbd740bcbdd70054885707
+Author: Damien Miller <djm@mindrot.org>
+Date: Sat Sep 15 19:35:40 2018 +1000
- Use libiaf on all sysv5 systems
+ remove accidentally checked-in authopt_fuzz binary
-commit bba02a5094b3db228ceac41cb4bfca165d0735f3
-Author: Tim Rice <tim@multitalents.net>
-Date: Sun Mar 25 09:17:33 2018 -0700
+commit beb9e522dc7717df08179f9e59f36b361bfa14ab
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Sep 14 05:26:27 2018 +0000
- modified: auth-sia.c
- modified: openbsd-compat/port-aix.c
- modified: openbsd-compat/port-uw.c
+ upstream: second try, deals properly with missing and private-only
- propogate changes to auth-passwd.c in commit
- 7c856857607112a3dfe6414696bf4c7ab7fb0cb3 to other providers
- of sys_auth_passwd()
+ Use consistent format in debug log for keys readied, offered and
+ received during public key authentication.
+
+ This makes it a little easier to see what is going on, as each message
+ now contains (where available) the key filename, its type and fingerprint,
+ and whether the key is hosted in an agent or a token.
+
+ OpenBSD-Commit-ID: f1c6a8e9cfc4e108c359db77f24f9a40e1e25ea7
-commit d7a7a39168bdfe273587bf85d779d60569100a3f
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Sat Mar 24 19:29:03 2018 +0000
+commit 6bc5a24ac867bfdc3ed615589d69ac640f51674b
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Sep 14 15:16:34 2018 +1000
- upstream: openssh-7.7
-
- OpenBSD-Commit-ID: 274e614352460b9802c905f38fb5ea7ed5db3d41
+ fuzzer harness for authorized_keys option parsing
-commit 9efcaaac314c611c6c0326e8bac5b486c424bbd2
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Sat Mar 24 19:28:43 2018 +0000
+commit 6c8b82fc6929b6a9a3f645151b6ec26c5507d9ef
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Sep 14 04:44:04 2018 +0000
- upstream: fix bogus warning when signing cert keys using agent;
+ upstream: revert following; deals badly with agent keys
- from djm; ok deraadt dtucker
+ revision 1.285
+ date: 2018/09/14 04:17:12; author: djm; state: Exp; lines: +47 -26; commitid: lflGFcNb2X2HebaK;
+ Use consistent format in debug log for keys readied, offered and
+ received during public key authentication.
- OpenBSD-Commit-ID: 12e50836ba2040042383a8b71e12d7ea06e9633d
-
-commit 393436024d2e4b4c7a01f9cfa5854e7437896d11
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Mar 25 09:40:46 2018 +1100
-
- Replace /dev/stdin with "-".
+ This makes it a little easier to see what is going on, as each message
+ now contains the key filename, its type and fingerprint, and whether
+ the key is hosted in an agent or a token.
- For some reason sftp -b doesn't work with /dev/stdin on Cygwin, as noted
- and suggested by vinschen at redhat.com.
+ OpenBSD-Commit-ID: e496bd004e452d4b051f33ed9ae6a54ab918f56d
-commit b5974de1a1d419e316ffb6524b1b277dda2f3b49
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Mar 23 13:21:14 2018 +1100
+commit 6da046f9c3374ce7e269ded15d8ff8bc45017301
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Sep 14 04:17:44 2018 +0000
- Provide $OBJ to paths in PuTTY interop tests.
+ upstream: garbage-collect moribund ssh_new_private() API.
+
+ OpenBSD-Commit-ID: 7c05bf13b094093dfa01848a9306c82eb6e95f6c
-commit dc31e79454e9b9140b33ad380565fdb59b9c4f33
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 16 09:06:31 2018 +0000
+commit 1f24ac5fc05252ceb1c1d0e8cab6a283b883c780
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Sep 14 04:17:12 2018 +0000
- upstream: Tell puttygen to use /dev/urandom instead of /dev/random. On
+ upstream: Use consistent format in debug log for keys readied,
- OpenBSD they are both non-blocking, but on many other -portable platforms it
- blocks, stalling tests.
+ offered and received during public key authentication.
- OpenBSD-Regress-ID: 397d0d4c719c353f24d79f5b14775e0cfdf0e1cc
+ This makes it a little easier to see what is going on, as each message
+ now contains the key filename, its type and fingerprint, and whether
+ the key is hosted in an agent or a token.
+
+ OpenBSD-Commit-ID: 2a01d59285a8a7e01185bb0a43316084b4f06a1f
-commit cb1f94431ef319cd48618b8b771b58739a8210cf
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Mar 22 07:06:11 2018 +0000
+commit 488c9325bb7233e975dbfbf89fa055edc3d3eddc
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Thu Sep 13 15:23:32 2018 +0000
- upstream: ssh/xmss: fix build; ok djm@
+ upstream: Fix warnings caused by user_from_uid() and group_from_gid()
- OpenBSD-Commit-ID: c9374ca41d4497f1c673ab681cc33f6e7c5dd186
+ now returning const char *.
+
+ OpenBSD-Commit-ID: b5fe571ea77cfa7b9035062829ab05eb87d7cc6f
-commit 27979da9e4074322611355598f69175b9ff10d39
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Mar 22 07:05:48 2018 +0000
+commit 0aa1f230846ebce698e52051a107f3127024a05a
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Sep 14 10:31:47 2018 +1000
- upstream: ssh/xmss: fix deserialize for certs; ok djm@
+ allow SIGUSR1 as synonym for SIGINFO
- OpenBSD-Commit-ID: f44c41636c16ec83502039828beaf521c057dddc
+ Lets users on those unfortunate operating systems that lack SIGINFO
+ still be able to obtain progress information from unit tests :)
-commit c6cb2565c9285eb54fa9dfbb3890f5464aff410f
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Mar 22 17:00:28 2018 +1100
+commit d64e78526596f098096113fcf148216798c327ff
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Sep 13 19:05:48 2018 +1000
- Save $? before case statement.
+ add compat header
+
+commit a3fd8074e2e2f06602e25618721f9556c731312c
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Sep 13 09:03:20 2018 +0000
+
+ upstream: missed a bit of openssl-1.0.x API in this unittest
- In some shells (FreeBSD 9, ash) the case statement resets $?, so save
- for later testing.
+ OpenBSD-Regress-ID: a73a54d7f7381856a3f3a2d25947bee7a9a5dbc9
-commit 4c4e7f783b43b264c247233acb887ee10ed4ce4d
+commit 86e0a9f3d249d5580390daf58e015e68b01cef10
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 14 05:35:40 2018 +0000
+Date: Thu Sep 13 05:06:51 2018 +0000
- upstream: rename recently-added "valid-before" key restriction to
+ upstream: use only openssl-1.1.x API here too
- "expiry-time" as the former is confusing wrt similar terminology in X.509;
- pointed out by jsing@
+ OpenBSD-Regress-ID: ae877064597c349954b1b443769723563cecbc8f
+
+commit 48f54b9d12c1c79fba333bc86d455d8f4cda8cfc
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Sep 13 12:13:50 2018 +1000
+
+ adapt -portable to OpenSSL 1.1x API
- OpenBSD-Regress-ID: ac8b41dbfd90cffd525d58350c327195b0937793
+ Polyfill missing API with replacement functions extracted from LibreSSL
-commit 500396b204c58e78ad9d081516a365a9f28dc3fd
+commit 86112951d63d48839f035b5795be62635a463f99
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Sep 13 12:12:42 2018 +1000
+
+ forgot to stage these test files in commit d70d061
+
+commit 482d23bcacdd3664f21cc82a5135f66fc598275f
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Mar 12 00:56:03 2018 +0000
+Date: Thu Sep 13 02:08:33 2018 +0000
- upstream: check valid-before option in authorized_keys
+ upstream: hold our collective noses and use the openssl-1.1.x API in
- OpenBSD-Regress-ID: 7e1e4a84f7f099a290e5a4cbf4196f90ff2d7e11
+ OpenSSH; feedback and ok tb@ jsing@ markus@
+
+ OpenBSD-Commit-ID: cacbcac87ce5da0d3ca7ef1b38a6f7fb349e4417
-commit a76b5d26c2a51d7dd7a5164e683ab3f4419be215
+commit d70d061828730a56636ab6f1f24fe4a8ccefcfc1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Mar 12 00:54:04 2018 +0000
+Date: Wed Sep 12 01:36:45 2018 +0000
- upstream: explicitly specify RSA/SHA-2 keytype here too
+ upstream: Include certs with multiple RSA signature variants in
- OpenBSD-Regress-ID: 74d7b24e8c72c27af6b481198344eb077e993a62
+ test data Ensure that cert->signature_key is populated correctly
+
+ OpenBSD-Regress-ID: 56e68f70fe46cb3a193ca207385bdb301fd6603a
-commit 3a43297ce29d37c64e37c7e21282cb219e28d3d1
+commit f803b2682992cfededd40c91818b653b5d923ef5
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Mar 12 00:52:57 2018 +0000
+Date: Wed Sep 12 01:23:48 2018 +0000
- upstream: exlicitly include RSA/SHA-2 keytypes in
+ upstream: test revocation by explicit hash and by fingerprint
- PubkeyAcceptedKeyTypes here
+ OpenBSD-Regress-ID: 079c18a9ab9663f4af419327c759fc1e2bc78fd8
+
+commit 2de78bc7da70e1338b32feeefcc6045cf49efcd4
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Sep 12 01:22:43 2018 +0000
+
+ upstream: s/sshkey_demote/sshkey_from_private/g
- OpenBSD-Regress-ID: 954d19e0032a74e31697fb1dc7e7d3d1b2d65fe9
+ OpenBSD-Regress-ID: 782bde7407d94a87aa8d1db7c23750e09d4443c4
-commit 037fdc1dc2d68e1d43f9c9e2586c02cabc8f7cc8
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Wed Mar 14 06:56:20 2018 +0000
+commit 41c115a5ea1cb79a6a3182773c58a23f760e8076
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Sep 12 16:50:01 2018 +1000
- upstream: sort expiry-time;
+ delete the correct thing; kexfuzz binary
+
+commit f0fcd7e65087db8c2496f13ed39d772f8e38b088
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Sep 12 06:18:59 2018 +0000
+
+ upstream: fix edit mistake; spotted by jmc@
- OpenBSD-Commit-ID: 8c7d82ee1e63e26ceb2b3d3a16514019f984f6bf
+ OpenBSD-Commit-ID: dd724e1c52c9d6084f4cd260ec7e1b2b138261c6
-commit abc0fa38c9bc136871f28e452c3465c3051fc785
+commit 4cc259bac699f4d2a5c52b92230f9e488c88a223
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 14 05:35:40 2018 +0000
+Date: Wed Sep 12 01:34:02 2018 +0000
- upstream: rename recently-added "valid-before" key restriction to
+ upstream: add SSH_ALLOWED_CA_SIGALGS - the default list of
- "expiry-time" as the former is confusing wrt similar terminology in X.509;
- pointed out by jsing@
+ signature algorithms that are allowed for CA signatures. Notably excludes
+ ssh-dsa.
- OpenBSD-Commit-ID: 376939466a1f562f3950a22314bc6505733aaae6
+ ok markus@
+
+ OpenBSD-Commit-ID: 1628e4181dc8ab71909378eafe5d06159a22deb4
-commit bf0fbf2b11a44f06a64b620af7d01ff171c28e13
+commit ba9e788315b1f6a350f910cb2a9e95b2ce584e89
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Mar 12 00:52:01 2018 +0000
+Date: Wed Sep 12 01:32:54 2018 +0000
- upstream: add valid-before="[time]" authorized_keys option. A
+ upstream: add sshkey_check_cert_sigtype() that checks a
- simple way of giving a key an expiry date. ok markus@
+ cert->signature_type against a supplied whitelist; ok markus
- OpenBSD-Commit-ID: 1793b4dd5184fa87f42ed33c7b0f4f02bc877947
+ OpenBSD-Commit-ID: caadb8073292ed7a9535e5adc067d11d356d9302
-commit fbd733ab7adc907118a6cf56c08ed90c7000043f
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Mar 12 19:17:26 2018 +1100
+commit a70fd4ad7bd9f2ed223ff635a3d41e483057f23b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Sep 12 01:31:30 2018 +0000
- Add AC_LANG_PROGRAM to AC_COMPILE_IFELSE.
+ upstream: add cert->signature_type field and keep it in sync with
- The recently added MIPS ABI tests need AC_LANG_PROGRAM to prevent
- warnings from autoconf. Pointed out by klausz at haus-gisela.de.
+ certificate signature wrt loading and certification operations; ok markus@
+
+ OpenBSD-Commit-ID: e8b8b9f76b66707a0cd926109c4383db8f664df3
-commit c7c458e8261b04d161763cd333d74e7a5842e917
+commit 357128ac48630a9970e3af0e6ff820300a28da47
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 7 23:53:08 2018 +0000
+Date: Wed Sep 12 01:30:10 2018 +0000
- upstream: revert recent strdelim() change, it causes problems with
+ upstream: Add "ssh -Q sig" to allow listing supported signature
- some configs.
+ algorithms ok markus@
- revision 1.124
- date: 2018/03/02 03:02:11; author: djm; state: Exp; lines: +19 -8; commitid: nNRsCijZiGG6SUTT;
- Allow escaped quotes \" and \' in ssh_config and sshd_config quotes
- option strings. bz#1596 ok markus@
+ OpenBSD-Commit-ID: 7a8c6eb6c249dc37823ba5081fce64876d10fe2b
+
+commit 9405c6214f667be604a820c6823b27d0ea77937d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Sep 12 01:21:34 2018 +0000
+
+ upstream: allow key revocation by SHA256 hash and allow ssh-keygen
- OpenBSD-Commit-ID: 59c40b1b81206d713c06b49d8477402c86babda5
+ to create KRLs using SHA256/base64 key fingerprints; ok markus@
+
+ OpenBSD-Commit-ID: a0590fd34e7f1141f2873ab3acc57442560e6a94
-commit 0bcd871ccdf3baf2b642509ba4773d5be067cfa2
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Mar 5 07:03:18 2018 +0000
+commit 50e2687ee0941c0ea216d6ffea370ffd2c1f14b9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Sep 12 01:19:12 2018 +0000
- upstream: move the input format details to -f; remove the output
+ upstream: log certificate fingerprint in authentication
- format details and point to sshd(8), where it is documented;
+ success/failure message (previously we logged only key ID and CA key
+ fingerprint).
- ok dtucker
+ ok markus@
- OpenBSD-Commit-ID: 95f17e47dae02a6ac7329708c8c893d4cad0004a
+ OpenBSD-Commit-ID: a8ef2d172b7f1ddbcce26d6434b2de6d94f6c05d
-commit 45011511a09e03493568506ce32f4891a174a3bd
-Author: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
-Date: Tue Jun 20 16:42:28 2017 +0100
+commit de37ca909487d23e5844aca289b3f5e75d3f1e1f
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Sep 7 04:26:56 2018 +0000
- configure.ac: properly set seccomp_audit_arch for MIPS64
+ upstream: Add FALLTHROUGH comments where appropriate. Patch from
- Currently seccomp_audit_arch is set to AUDIT_ARCH_MIPS64 or
- AUDIT_ARCH_MIPSEL64 (depending on the endinness) when openssh is built
- for MIPS64. However, that's only valid for n64 ABI. The right macros for
- n32 ABI defined in seccomp.h are AUDIT_ARCH_MIPS64N32 and
- AUDIT_ARCH_MIPSEL64N32, for big and little endian respectively.
+ jjelen at redhat via bz#2687.
- Because of that an sshd built for MIPS64 n32 rejects connection attempts
- and the output of strace reveals that the problem is related to seccomp
- audit:
+ OpenBSD-Commit-ID: c48eb457be697a19d6d2950c6d0879f3ccc851d3
+
+commit 247766cd3111d5d8c6ea39833a3257ca8fb820f2
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Sep 7 01:42:54 2018 +0000
+
+ upstream: ssh -MM requires confirmation for all operations that
- [pid 194] prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=57,
- filter=0x555d5da0}) = 0
- [pid 194] write(7, "\0\0\0]\0\0\0\5\0\0\0Ulist_hostkey_types: "..., 97) = ?
- [pid 193] <... poll resumed> ) = 2 ([{fd=5, revents=POLLIN|POLLHUP},
- {fd=6, revents=POLLHUP}])
- [pid 194] +++ killed by SIGSYS +++
+ change the multiplexing state, not just new sessions.
- This patch fixes that problem by setting the right value to
- seccomp_audit_arch taking into account the MIPS64 ABI.
+ mention that confirmation is checked via ssh-askpass
- Signed-off-by: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
+ OpenBSD-Commit-ID: 0f1b45551ebb9cc5c9a4fe54ad3b23ce90f1f5c2
-commit 580086704c31de91dc7ba040a28e416bf1fefbca
-Author: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
-Date: Tue Jun 20 16:42:11 2017 +0100
+commit db8bb80e3ac1bcb3e1305d846cd98c6b869bf03f
+Author: mestre@openbsd.org <mestre@openbsd.org>
+Date: Tue Aug 28 12:25:53 2018 +0000
- configure.ac: detect MIPS ABI
+ upstream: fix misplaced parenthesis inside if-clause. it's harmless
- Signed-off-by: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
+ and the only issue is showing an unknown error (since it's not defined)
+ during fatal(), if it ever an error occurs inside that condition.
+
+ OK deraadt@ markus@ djm@
+
+ OpenBSD-Commit-ID: acb0a8e6936bfbe590504752d01d1d251a7101d8
-commit cd4e937aa701f70366cd5b5969af525dff6fdf15
-Author: Alan Yee <alyee@ucsd.edu>
-Date: Wed Mar 7 15:12:14 2018 -0800
+commit 086cc614f550b7d4f100c95e472a6b6b823938ab
+Author: mestre@openbsd.org <mestre@openbsd.org>
+Date: Tue Aug 28 12:17:45 2018 +0000
- Use https URLs for links that support it.
+ upstream: fix build with DEBUG_PK enabled
+
+ OK dtucker@
+
+ OpenBSD-Commit-ID: ec1568cf27726e9638a0415481c20c406e7b441c
-commit c0a0c3fc4a76b682db22146b28ddc46566db1ce9
+commit 2678833013e97f8b18f09779b7f70bcbf5eb2ab2
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Mar 5 20:03:07 2018 +1100
+Date: Fri Sep 7 14:41:53 2018 +1000
- Disable UTMPX on SunOS4.
+ Handle ngroups>_SC_NGROUPS_MAX.
+
+ Based on github pull request #99 from Darren Maffat at Oracle: Solaris'
+ getgrouplist considers _SC_NGROUPS_MAX more of a guideline and can return
+ a larger number of groups. In this case, retry getgrouplist with a
+ larger array and defer allocating groups_byname. ok djm@
-commit 58fd4c5c0140f6636227ca7acbb149ab0c2509b9
+commit 039bf2a81797b8f3af6058d34005a4896a363221
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Mar 5 19:28:08 2018 +1100
+Date: Fri Sep 7 14:06:57 2018 +1000
- Check for and work around buggy fflush(NULL).
+ Initial len for the fmt=NULL case.
- Some really old platforms (eg SunOS4) segfault on fflush(NULL) so check
- for and work around. With klausz at haus-gisela.de.
+ Patch from jjelen at redhat via bz#2687. (OpenSSH never calls
+ setproctitle with a null format so len is always initialized).
-commit 71e48bc7945f867029e50e06c665c66aed6d3c64
+commit ea9c06e11d2e8fb2f4d5e02f8a41e23d2bd31ca9
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Mar 5 10:22:32 2018 +1100
+Date: Fri Sep 7 14:01:39 2018 +1000
- Remove extra XMSS #endif
+ Include stdlib.h.
- Extra #endif breaks compile with -DWITH_XMSS. Pointed out by Jack
- Schmidt via github.
+ Patch from jjelen at redhat via bz#2687.
-commit 055e09e2212ff52067786bf6d794ca9512ff7f0c
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sat Mar 3 06:37:53 2018 +0000
+commit 9617816dbe73ec4d65075f4d897443f63a97c87f
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Aug 27 13:08:01 2018 +1000
- upstream: Update RSA minimum modulus size to 1024. sshkey.h rev 1.18
+ document some more regress control env variables
- bumped the minimum from 768 to 1024, update man page accordingly.
+ Specifically SKIP_UNIT, USE_VALGRING and LTESTS. Sort the list of
+ environment variables.
- OpenBSD-Commit-ID: 27563ab4e866cd2aac40a5247876f6787c08a338
+ Based on patch from Jakub Jelen
-commit 7e4fadd3248d6bb7d39d6688c76a613d35d2efc1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Mar 4 01:46:48 2018 +0000
+commit 71508e06fab14bc415a79a08f5535ad7bffa93d9
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Aug 23 15:41:42 2018 +1000
- upstream: for the pty control tests, just check that the PTY path
-
- points to something in /dev (rather than checking the device node itself);
- makes life easier for portable, where systems with dynamic ptys can delete
- nodes before we get around to testing their existence.
+ shorten temporary SSH_REGRESS_TMP path
- OpenBSD-Regress-ID: b1e455b821e62572bccd98102f8dd9d09bb94994
+ Previous path was exceeding max socket length on at least one platform (OSX)
-commit 13ef4cf53f24753fe920832b990b25c9c9cd0530
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Mar 3 16:21:20 2018 +1100
+commit 26739cf5bdc9030a583b41ae5261dedd862060f0
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Aug 23 13:06:02 2018 +1000
- Update PAM password change to new opts API.
+ rebuild dependencies
-commit 33561e68e0b27366cb769295a077aabc6a49d2a1
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Mar 3 14:56:09 2018 +1100
+commit ff729025c7463cf5d0a8d1ca1823306e48c6d4cf
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Aug 23 13:03:32 2018 +1000
- Add strndup for platforms that need it.
+ fix path in distclean target
- Some platforms don't have strndup, which includes Solaris 10, NetBSD 3
- and FreeBSD 6.
+ Patch from Jakub Jelen
-commit e8a17feba95eef424303fb94441008f6c5347aaf
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Mar 3 14:49:07 2018 +1100
+commit 7fef173c28f7462dcd8ee017fdf12b5073f54c02
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Aug 23 03:01:08 2018 +0000
- Flatten and alphabetize object file lists.
+ upstream: memleak introduced in r1.83; from Colin Watson
- This will make maintenance and changes easier. "no objection" tim@
+ OpenBSD-Commit-ID: 5c019104c280cbd549a264a7217b67665e5732dc
-commit de1920d743d295f50e6905e5957c4172c038e8eb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 3 03:16:17 2018 +0000
+commit b8ae02a2896778b8984c7f51566c7f0f56fa8b56
+Author: schwarze@openbsd.org <schwarze@openbsd.org>
+Date: Tue Aug 21 13:56:27 2018 +0000
- upstream: unit tests for new authorized_keys options API
+ upstream: AIX reports the CODESET as "ISO8859-1" in the POSIX locale.
- OpenBSD-Regress-ID: 820f9ec9c6301f6ca330ad4052d85f0e67d0bdc1
+ Treating that as a safe encoding is OK because even when other systems return
+ that string for real ISO8859-1, it is still safe in the sense that it is
+ ASCII-compatible and stateless.
+
+ Issue reported by Val dot Baranov at duke dot edu. Additional
+ information provided by Michael dot Felt at felt dot demon dot nl.
+ Tested by Michael Felt on AIX 6.1 and by Val Baranov on AIX 7.1.
+ Tweak and OK djm@.
+
+ OpenBSD-Commit-ID: 36f1210e0b229817d10eb490d6038f507b8256a7
-commit dc3e92df17556dc5b0ab19cee8dcb2a6ba348717
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 2 02:53:27 2018 +0000
+commit bc44ee088ad269d232e514f037c87ada4c2fd3f0
+Author: Tim Rice <tim@multitalents.net>
+Date: Tue Aug 21 08:57:24 2018 -0700
- upstream: fix testing of pty option, include positive test and
+ modified: openbsd-compat/port-uw.c
+ remove obsolete and un-needed include
+
+commit 829fc28a9c54e3f812ee7248c7a3e31eeb4f0b3a
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Aug 20 15:57:29 2018 +1000
+
+ Missing unistd.h for regress/mkdtemp.c
+
+commit c8313e492355a368a91799131520d92743d8d16c
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Aug 17 05:45:20 2018 +1000
+
+ update version numbers in anticipation of release
+
+commit 477b49a34b89f506f4794b35e3c70b3e2e83cd38
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Mon Aug 13 17:08:51 2018 +0200
+
+ configure: work around GCC shortcoming on Cygwin
- testing of restrict keyword
+ Cygwin's latest 7.x GCC allows to specify -mfunction-return=thunk
+ as well as -mindirect-branch=thunk on the command line, albeit
+ producing invalid code, leading to an error at link stage.
- OpenBSD-Regress-ID: 4268f27c2706a0a95e725d9518c5bcbec9814c6d
+ The check in configure.ac only checks if the option is present,
+ but not if it produces valid code.
+
+ This patch fixes it by special-casing Cygwin. Another solution
+ may be to change these to linker checks.
+
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
-commit 3d1edd1ebbc0aabea8bbe61903060f37137f7c61
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 2 02:51:55 2018 +0000
+commit b0917945efa374be7648d67dbbaaff323ab39edc
+Author: Corinna Vinschen <vinschen@redhat.com>
+Date: Mon Aug 13 17:05:05 2018 +0200
- upstream: better testing for port-forwarding and restrict flags in
+ cygwin: add missing stdarg.h include
- authorized_keys
+ Further header file standarization in Cygwin uncovered a lazy
+ indirect include in bsd-cygwin_util.c
- OpenBSD-Regress-ID: ee771df8955f2735df54746872c6228aff381daa
+ Signed-off-by: Corinna Vinschen <vinschen@redhat.com>
-commit 7c856857607112a3dfe6414696bf4c7ab7fb0cb3
+commit c3903c38b0fd168ab3d925c2b129d1a599593426
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 3 03:15:51 2018 +0000
+Date: Mon Aug 13 02:41:05 2018 +0000
- upstream: switch over to the new authorized_keys options API and
+ upstream: revert compat.[ch] section of the following change. It
- remove the legacy one.
+ causes double-free under some circumstances.
- Includes a fairly big refactor of auth2-pubkey.c to retain less state
- between key file lines.
+ --
- feedback and ok markus@
+ date: 2018/07/31 03:07:24; author: djm; state: Exp; lines: +33 -18; commitid: f7g4UI8eeOXReTPh;
+ fix some memory leaks spotted by Coverity via Jakub Jelen in bz#2366
+ feedback and ok dtucker@
- OpenBSD-Commit-ID: dece6cae0f47751b9892080eb13d6625599573df
+ OpenBSD-Commit-ID: 1e77547f60fdb5e2ffe23e2e4733c54d8d2d1137
-commit 90c4bec8b5f9ec4c003ae4abdf13fc7766f00c8b
+commit 1b9dd4aa15208100fbc3650f33ea052255578282
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 3 03:06:02 2018 +0000
+Date: Sun Aug 12 20:19:13 2018 +0000
- upstream: Introduce a new API for handling authorized_keys options.
-
- This API parses options to a dedicated structure rather than the old API's
- approach of setting global state. It also includes support for merging
- options, e.g. from authorized_keys, authorized_principals and/or
- certificates.
+ upstream: better diagnosics on alg list assembly errors; ok
- feedback and ok markus@
+ deraadt@ markus@
- OpenBSD-Commit-ID: 98badda102cd575210d7802943e93a34232c80a2
+ OpenBSD-Commit-ID: 5a557e74b839daf13cc105924d2af06a1560faee
-commit 26074380767e639ef89321610e146ae11016b385
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 3 03:01:50 2018 +0000
+commit e36a5f61b0f5bebf6d49c215d228cd99dfe86e28
+Author: Damien Miller <djm@mindrot.org>
+Date: Sat Aug 11 18:08:45 2018 -0700
- upstream: warn when the agent returns a signature type that was
+ Some AIX fixes; report from Michael Felt
+
+commit 2f4766ceefe6657c5ad5fe92d13c411872acae0e
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Aug 10 01:35:49 2018 +0000
+
+ upstream: The script that cooks up PuTTY format host keys does not
- different to what was requested. This might happen when an old/non-OpenSSH
- agent is asked to make a rsa-sha2-256/512 signature but only supports
- ssh-rsa. bz#2799 feedback and ok markus@
+ understand the new key format so convert back to old format to create the
+ PuTTY key and remove it once done.
- OpenBSD-Commit-ID: 760c0f9438c5c58abc16b5f98008ff2d95cb13ce
+ OpenBSD-Regress-ID: 2a449a18846c3a144bc645135b551ba6177e38d3
-commit f493d2b0b66fb003ed29f31dd66ff1aeb64be1fc
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Mar 2 21:40:15 2018 +0000
+commit e1b26ce504662a5d5b991091228984ccfd25f280
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Aug 10 00:44:01 2018 +0000
- upstream: apply a lick of paint; tweaks/ok dtucker
+ upstream: improve
- OpenBSD-Commit-ID: 518a6736338045e0037f503c21027d958d05e703
+ OpenBSD-Commit-ID: 40d839db0977b4e7ac8b647b16d5411d4faf2f60
-commit 713d9cb510e0e7759398716cbe6dcf43e574be71
+commit 7c712966a3139622f7fb55045368d05de4e6782c
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 2 03:02:11 2018 +0000
+Date: Fri Aug 10 00:42:29 2018 +0000
- upstream: Allow escaped quotes \" and \' in ssh_config and
+ upstream: Describe pubkey format, prompted by bz#2853
- sshd_config quotes option strings. bz#1596 ok markus@
+ While I'm here, describe and link to the remaining local PROTOCOL.*
+ docs that weren't already mentioned (PROTOCOL.key, PROTOCOL.krl and
+ PROTOCOL.mux)
- OpenBSD-Commit-ID: dd3a29fc2dc905e8780198e5a6a30b096de1a1cb
+ OpenBSD-Commit-ID: 2a900f9b994ba4d53e7aeb467d44d75829fd1231
-commit 94b4e2d29afaaaef89a95289b16c18bf5627f7cd
+commit ef100a2c5a8ed83afac0b8f36520815803da227a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 2 02:08:03 2018 +0000
+Date: Fri Aug 10 00:27:15 2018 +0000
- upstream: refactor sshkey_read() to make it a little more, err,
-
- readable. ok markus
+ upstream: fix numbering
- OpenBSD-Commit-ID: 2e9247b5762fdac3b6335dc606d3822121714c28
+ OpenBSD-Commit-ID: bc7a1764dff23fa4c5ff0e3379c9c4d5b63c9596
-commit 5886b92968b360623491699247caddfb77a74d80
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Mar 1 20:32:16 2018 +0000
+commit ed7bd5d93fe14c7bd90febd29b858ea985d14d45
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Aug 8 01:16:01 2018 +0000
- upstream: missing #ifdef for _PATH_HOST_XMSS_KEY_FILE; report by
+ upstream: Use new private key format by default. This format is
- jmc@
+ suported by OpenSSH >= 6.5 (released January 2014), so it should be supported
+ by most OpenSSH versions in active use.
- OpenBSD-Commit-ID: 9039cb69a3f9886bfef096891a9e7fcbd620280b
+ It is possible to convert new-format private keys to the older
+ format using "ssh-keygen -f /path/key -pm PEM".
+
+ ok deraadt dtucker
+
+ OpenBSD-Commit-ID: e3bd4f2509a2103bfa2f710733426af3ad6d8ab8
-commit 3b36bed3d26f17f6a2b7e036e01777770fe1bcd4
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Feb 26 12:14:53 2018 +0000
+commit 967226a1bdde59ea137e8f0df871854ff7b91366
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Aug 4 00:55:06 2018 +0000
- upstream: Remove unneeded (local) include. ok markus@
+ upstream: invalidate dh->priv_key after freeing it in error path;
- OpenBSD-Commit-ID: 132812dd2296b1caa8cb07d2408afc28e4e60f93
+ avoids unlikely double-free later. Reported by Viktor Dukhovni via
+ https://github.com/openssh/openssh-portable/pull/96 feedback jsing@ tb@
+
+ OpenBSD-Commit-ID: e317eb17c3e05500ae851f279ef6486f0457c805
-commit 27b9f3950e0289e225b57b7b880a8f1859dcd70b
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Feb 26 03:56:44 2018 +0000
+commit 74287f5df9966a0648b4a68417451dd18f079ab8
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jul 31 03:10:27 2018 +0000
- upstream: Add $OpenBSD$ markers to xmss files to help keep synced
+ upstream: delay bailout for invalid authentic
- with portable. ok djm@.
+ =?UTF-8?q?ating=20user=20until=20after=20the=20packet=20containing=20the?=
+ =?UTF-8?q?=20request=20has=20been=20fully=20parsed.=20Reported=20by=20Dar?=
+ =?UTF-8?q?iusz=20Tytko=20and=20Micha=C5=82=20Sajdak;=20ok=20deraadt?=
+ MIME-Version: 1.0
+ Content-Type: text/plain; charset=UTF-8
+ Content-Transfer-Encoding: 8bit
- OpenBSD-Commit-ID: 5233a27aafd1dfadad4b957225f95ae51eb365c1
+ OpenBSD-Commit-ID: b4891882fbe413f230fe8ac8a37349b03bd0b70d
-commit afd830847a82ebbd5aeab05bad6d2c8ce74df1cd
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Feb 26 03:03:05 2018 +0000
+commit 1a66079c0669813306cc69e5776a4acd9fb49015
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jul 31 03:07:24 2018 +0000
- upstream: Add newline at end of file to prevent compiler warnings.
+ upstream: fix some memory leaks spotted by Coverity via Jakub Jelen
- OpenBSD-Commit-ID: 52f247d4eafe840c7c14c8befa71a760a8eeb063
+ in bz#2366 feedback and ok dtucker@
+
+ OpenBSD-Commit-ID: 8402bbae67d578bedbadb0ce68ff7c5a136ef563
-commit 941e0d3e9bb8d5e4eb70cc694441445faf037c84
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Feb 28 19:59:35 2018 +1100
+commit 87f08be054b7eeadbb9cdeb3fb4872be79ccf218
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jul 20 13:18:28 2018 +1000
- Add WITH_XMSS, move to prevent conflicts.
+ Remove support for S/Key
- Add #ifdef WITH_XMSS to ssh-xmss.c, move it in the other files to after
- includes.h so it's less likely to conflict and will pick up WITH_XMSS if
- added to config.h.
+ Most people will 1) be using modern multi-factor authentication methods
+ like TOTP/OATH etc and 2) be getting support for multi-factor
+ authentication via PAM or BSD Auth.
-commit a10d8552d0d2438da4ed539275abcbf557d1e7a8
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 27 14:45:17 2018 +1100
+commit 5d14019ba2ff54acbfd20a6b9b96bb860a8c7c31
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Fri Jul 27 12:03:17 2018 +0000
- Conditionally compile XMSS code.
+ upstream: avoid expensive channel_open_message() calls; ok djm@
- The XMSS code is currently experimental and, unlike the rest of OpenSSH
- cannot currently be compiled with a c89 compiler.
+ OpenBSD-Commit-ID: aea3b5512ad681cd8710367d743e8a753d4425d9
-commit 146c3bd28c8dbee9c4b06465d9c9facab96b1e9b
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 12:51:29 2018 +1100
+commit e655ee04a3cb7999dbf9641b25192353e2b69418
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jul 27 05:34:42 2018 +0000
- Check dlopen has RTLD_NOW before enabling pkcs11.
+ upstream: Now that ssh can't be setuid, remove the
+
+ original_real_uid and original_effective_uid globals and replace with calls
+ to plain getuid(). ok djm@
+
+ OpenBSD-Commit-ID: 92561c0cd418d34e6841e20ba09160583e27b68c
-commit 1323f120d06a26074c4d154fcbe7f49bcad3d741
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 27 08:41:25 2018 +1100
+commit 73ddb25bae4c33a0db361ac13f2e3a60d7c6c4a5
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jul 27 05:13:02 2018 +0000
- Check for attributes on prototype args.
+ upstream: Remove uid checks from low port binds. Now that ssh
- Some compilers (gcc 2.9.53, 3.0 and probably others, see gcc bug #3481)
- do not accept __attribute__ on function pointer prototype args. Check for
- this and hide them if they're not accepted.
+ cannot be setuid and sshd always has privsep on, we can remove the uid checks
+ for low port binds and just let the system do the check. We leave a sanity
+ check for the !privsep case so long as the code is stil there. with & ok
+ djm@
+
+ OpenBSD-Commit-ID: 9535cfdbd1cd54486fdbedfaee44ce4367ec7ca0
-commit f0b245b0439e600fab782d19e97980e9f2c2533c
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 11:43:48 2018 +1100
+commit c12033e102760d043bc5c98e6c8180e4d331b0df
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jul 27 03:55:22 2018 +0000
- Check if HAVE_DECL_BZERO correctly.
+ upstream: ssh(1) no longer supports being setuid root. Remove reference
+
+ to crc32 which went with protocol 1. Pointed out by deraadt@.
+
+ OpenBSD-Commit-ID: f8763c25fd96ed91dd1abdab5667fd2e27e377b6
-commit c7ef4a399155e1621a532cc5e08e6fa773658dd4
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 17:42:56 2018 +1100
+commit 4492e2ec4e1956a277ef507f51d66e5c2aafaaf8
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jul 27 14:15:28 2018 +1000
- Wrap <stdint.h> in #ifdef HAVE_STDINT_H.
+ correct snprintf truncation check in closefrom()
+
+ Truncation cannot happen unless the system has set PATH_MAX to some
+ nonsensically low value.
+
+ bz#2862, patch from Daniel Le
-commit ac53ce46cf8165cbda7f57ee045f9f32e1e92b31
+commit 149cab325a8599a003364ed833f878449c15f259
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 16:24:23 2018 +1100
+Date: Fri Jul 27 13:46:06 2018 +1000
- Replace $(CURDIR) with $(PWD).
-
- The former doesn't work on Solaris or BSDs.
+ Include stdarg.h in mkdtemp for va_list.
-commit 534b2680a15d14e7e60274d5b29b812d44cc5a44
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 14:51:59 2018 +1100
+commit 6728f31bdfdc864d192773c32465b1860e23f556
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Wed Jul 25 17:12:35 2018 +0000
- Comment out hexdump().
+ upstream: Don't redefine Makefile choices which come correct from
- Nothing currently uses them but they cause conflicts on at least
- FreeBSD, possibly others. ok djm@
+ bsd.*.mk ok markus
+
+ OpenBSD-Commit-ID: 814b2f670df75759e1581ecef530980b2b3d7e0f
-commit 5aea4aa522f61bb2f34c3055a7de203909dfae77
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 14:39:14 2018 +1100
+commit 21fd477a855753c1a8e450963669e28e39c3b5d2
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Wed Jul 25 13:56:23 2018 +0000
- typo: missing ;
+ upstream: fix indent; Clemens Goessnitzer
+
+ OpenBSD-Commit-ID: b5149a6d92b264d35f879d24608087b254857a83
-commit cd3ab57f9b388f8b1abf601dc4d78ff82d83b75e
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 14:37:06 2018 +1100
+commit 8e433c2083db8664c41499ee146448ea7ebe7dbf
+Author: beck@openbsd.org <beck@openbsd.org>
+Date: Wed Jul 25 13:10:56 2018 +0000
- Hook up flock() compat code.
+ upstream: Use the caller provided (copied) pwent struct in
- Also a couple of minor changes: fail if we can't lock instead of
- silently succeeding, and apply a couple of minor style fixes.
+ load_public_identity_files instead of calling getpwuid() again and discarding
+ the argument. This prevents a client crash where tilde_expand_filename calls
+ getpwuid() again before the pwent pointer is used. Issue noticed and reported
+ by Pierre-Olivier Martel <pom@apple.com> ok djm@ deraadt@
+
+ OpenBSD-Commit-ID: a067d74b5b098763736c94cc1368de8ea3f0b157
-commit b087998d1ba90dd1ddb6bfdb17873dc3e7392798
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 14:27:02 2018 +1100
+commit e2127abb105ae72b6fda64fff150e6b24b3f1317
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Mon Jul 23 19:53:55 2018 +0000
- Import flock() compat from NetBSD.
+ upstream: oops, failed to notice that SEE ALSO got messed up;
- From NetBSD's src/trunk/tools/compat/flock.c, no OpenSSH changes yet.
+ OpenBSD-Commit-ID: 61c1306542cefdc6e59ac331751afe961557427d
-commit 89212533dde6798324e835b1499084658df4579e
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 26 12:32:14 2018 +1100
+commit ddf1b797c2d26bbbc9d410aa4f484cbe94673587
+Author: kn@openbsd.org <kn@openbsd.org>
+Date: Mon Jul 23 19:02:49 2018 +0000
- Fix breakage when REGRESSTMP not set.
+ upstream: Point to glob in section 7 for the actual list of special
- BUILDDIR is not set where used for REGRESSTMP, use make's CURDIR
- instead. Pointed out by djm@.
+ characters instead the C API in section 3.
+
+ OK millert jmc nicm, "the right idea" deraadt
+
+ OpenBSD-Commit-ID: a74fd215488c382809e4d041613aeba4a4b1ffc6
-commit f885474137df4b89498c0b8834c2ac72c47aa4bd
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 26 12:18:14 2018 +1100
+commit 01c98d9661d0ed6156e8602b650f72eed9fc4d12
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Jul 22 12:16:59 2018 +0000
- XMSS-related files get includes.h
+ upstream: Switch authorized_keys example from ssh-dss to ssh-rsa
+
+ since the former is no longer enabled by default. Pointed out by Daniel A.
+ Maierhofer, ok jmc
+
+ OpenBSD-Commit-ID: 6a196cef53d7524e0c9b58cdbc1b5609debaf8c7
-commit 612faa34c72e421cdc9e63f624526bae62d557cc
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 26 12:17:55 2018 +1100
+commit 472269f8fe19343971c2d08f504ab5cbb8234b33
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jul 20 05:01:10 2018 +0000
- object files end with .o - not .c
+ upstream: slightly-clearer description for AuthenticationMethods - the
+
+ lists have comma-separated elements; bz#2663 from Hans Meier
+
+ OpenBSD-Commit-ID: 931c983d0fde4764d0942fb2c2b5017635993b5a
-commit bda709b8e13d3eef19e69c2d1684139e3af728f5
+commit c59aca8adbdf7f5597084ad360a19bedb3f80970
Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 26 12:17:22 2018 +1100
+Date: Fri Jul 20 14:53:42 2018 +1000
- avoid inclusion of deprecated selinux/flask.h
+ Create control sockets in clean temp directories
- Use string_to_security_class() instead.
+ Adds a regress/mkdtemp tool and uses it to create empty temp
+ directories for tests needing control sockets.
+
+ Patch from Colin Watson via bz#2660; ok dtucker
-commit 2e396439365c4ca352cac222717d09b14f8a0dfd
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Feb 26 11:48:27 2018 +1100
+commit 6ad8648e83e4f4ace37b742a05c2a6b6b872514e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jul 20 03:46:34 2018 +0000
- updatedepend
+ upstream: remove unused zlib.h
+
+ OpenBSD-Commit-ID: 8d274a9b467c7958df12668b49144056819f79f1
-commit 1b11ea7c58cd5c59838b5fa574cd456d6047b2d4
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Fri Feb 23 15:58:37 2018 +0000
+commit 3ba6e6883527fe517b6e4a824876e2fe62af22fc
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Jul 19 23:03:16 2018 +0000
- upstream: Add experimental support for PQC XMSS keys (Extended
+ upstream: Fix typo in comment. From Alexandru Iacob via github.
- Hash-Based Signatures) The code is not compiled in by default (see WITH_XMSS
- in Makefile.inc) Joint work with stefan-lukas_gazdag at genua.eu See
- https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12 ok
+ OpenBSD-Commit-ID: eff4ec07c6c8c5483533da43a4dda37d72ef7f1d
+
+commit c77bc73c91bc656e343a1961756e09dd1b170820
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Jul 20 13:48:51 2018 +1000
+
+ Explicitly include openssl before zlib.
+
+ Some versions of OpenSSL have "free_func" in their headers, which zlib
+ typedefs. Including openssl after zlib (eg via sshkey.h) results in
+ "syntax error before `free_func'", which this fixes.
+
+commit 95d41e90eafcd1286a901e8e361e4a37b98aeb52
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Jul 19 10:28:47 2018 +0000
+
+ upstream: Deprecate UsePrivilegedPort now that support for running
+
+ ssh(1) setuid has been removed, remove supporting code and clean up
+ references to it in the man pages
+
+ We have not shipped ssh(1) the setuid bit since 2002. If ayone
+ really needs to make connections from a low port number this can
+ be implemented via a small setuid ProxyCommand.
+
+ ok markus@ jmc@ djm@
+
+ OpenBSD-Commit-ID: d03364610b7123ae4c6792f5274bd147b6de717e
+
+commit 258dc8bb07dfb35a46e52b0822a2c5b7027df60a
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Jul 18 11:34:04 2018 +0000
+
+ upstream: Remove support for running ssh(1) setuid and fatal if
+
+ attempted. Do not link uidwap.c into ssh any more. Neuters
+ UsePrivilegedPort, which will be marked as deprecated shortly. ok markus@
djm@
- OpenBSD-Commit-ID: ef3eccb96762a5d6f135d7daeef608df7776a7ac
+ OpenBSD-Commit-ID: c4ba5bf9c096f57a6ed15b713a1d7e9e2e373c42
-commit 7d330a1ac02076de98cfc8fda05353d57b603755
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Feb 23 07:38:09 2018 +0000
+commit ac590760b251506b0a152551abbf8e8d6dc2f527
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jul 16 22:25:01 2018 +0000
- upstream: some cleanup for BindInterface and ssh-keyscan;
+ upstream: Slot 0 in the hostbased key array was previously RSA1,
- OpenBSD-Commit-ID: 1a719ebeae22a166adf05bea5009add7075acc8c
+ but that is now gone and the slot is unused so remove it. Remove two
+ now-unused macros, and add an array bounds check to the two remaining ones
+ (array is statically sized, so mostly a safety check on future changes). ok
+ markus@
+
+ OpenBSD-Commit-ID: 2e4c0ca6cc1d8daeccead2aa56192a3f9d5e1e7a
-commit c7b5a47e3b9db9a0f0198f9c90c705f6307afc2b
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 25 23:55:41 2018 +1100
+commit 26efc2f5df0e3bcf6a6bbdd0506fd682d60c2145
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jul 16 11:05:41 2018 +0000
- Invert sense of getpgrp test.
+ upstream: Remove support for loading HostBasedAuthentication keys
- AC_FUNC_GETPGRP tests if getpgrp(0) works, which it does if it's not
- declared. Instead, test if the zero-arg version we want to use works.
+ directly in ssh(1) and always use ssh-keysign. This removes one of the few
+ remaining reasons why ssh(1) might be setuid. ok markus@
+
+ OpenBSD-Commit-ID: 97f01e1448707129a20d75f86bad5d27c3cf0b7d
-commit b39593a6de5290650a01adf8699c6460570403c2
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 25 13:25:15 2018 +1100
+commit 3eb7f1038d17af7aea3c2c62d1e30cd545607640
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jul 16 07:06:50 2018 +0000
- Add no-op getsid implmentation.
+ upstream: keep options.identity_file_userprovided array in sync when we
+
+ load keys, fixing some spurious error messages; ok markus
+
+ OpenBSD-Commit-ID: c63e3d5200ee2cf9e35bda98de847302566c6a00
-commit 11057564eb6ab8fd987de50c3d7f394c6f6632b7
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 25 11:22:57 2018 +1100
+commit 2f131e1b34502aa19f345e89cabf6fa3fc097f09
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jul 16 03:09:59 2018 +0000
- bsd-statvfs: include sys/vfs.h, check for f_flags.
+ upstream: memleak in unittest; found by valgrind
+
+ OpenBSD-Regress-ID: 168c23b0fb09fc3d0b438628990d3fd9260a8a5e
-commit e9dede06e5bc582a4aeb5b1cd5a7a640d7de3609
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 25 10:20:31 2018 +1100
+commit de2997a4cf22ca0a524f0e5b451693c583e2fd89
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jul 16 03:09:13 2018 +0000
- Handle calloc(0,x) where different from malloc.
+ upstream: memleaks; found by valgrind
- Configure assumes that if malloc(0) returns null then calloc(0,n)
- also does. On some old platforms (SunOS4) malloc behaves as expected
- (as determined by AC_FUNC_MALLOC) but calloc doesn't. Test for this
- at configure time and activate the replacement function if found, plus
- handle this case in rpl_calloc.
+ OpenBSD-Commit-ID: 6c3ba22be53e753c899545f771e8399fc93cd844
-commit 2eb4041493fd2635ffdc64a852d02b38c4955e0b
+commit 61cc0003eb37fa07603c969c12b7c795caa498f3
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 24 21:06:48 2018 +1100
+Date: Sat Jul 14 16:49:01 2018 +1000
- Add prototype for readv if needed.
+ Undef a few new macros in sys-queue.h.
+
+ Prevents macro redefinition warnings on OSX.
-commit 6c8c9a615b6d31db8a87bc25033f053d5b0a831e
+commit 30a2c213877a54a44dfdffb6ca8db70be5b457e0
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 24 20:46:37 2018 +1100
+Date: Fri Jul 13 13:40:20 2018 +1000
- Check for raise and supply if needed.
+ Include unistd.h for geteuid declaration.
-commit a9004425a032d7a7141a5437cfabfd02431e2a74
+commit 1dd32c23f2a85714dfafe2a9cc516971d187caa4
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 24 20:25:22 2018 +1100
+Date: Fri Jul 13 13:38:10 2018 +1000
- Check for bzero and supply if needed.
+ Fallout from buffer conversion in AUDIT_EVENTS.
- Since explicit_bzero uses it via an indirect it needs to be a function
- not just a macro.
+ Supply missing "int r" and fix error path for sshbuf_new().
-commit 1a348359e4d2876203b5255941bae348557f4f54
+commit 7449c178e943e5c4f6c8416a4e41d93b70c11c9e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 23 05:14:05 2018 +0000
+Date: Fri Jul 13 02:13:50 2018 +0000
- upstream: Add ssh-keyscan -D option to make it print its results in
+ upstream: make this use ssh_proxy rather than starting/stopping a
- SSHFP format bz#2821, ok dtucker@
+ daemon for each testcase
- OpenBSD-Commit-ID: 831446b582e0f298ca15c9d99c415c899e392221
+ OpenBSD-Regress-ID: 608b7655ea65b1ba8fff5a13ce9caa60ef0c8166
-commit 3e19fb976a47b44b3d7c4f8355269f7f2c5dd82c
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 23 04:18:46 2018 +0000
+commit dbab02f9208d9baa134cec1d007054ec82b96ca9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jul 13 02:13:19 2018 +0000
- upstream: Add missing braces.
+ upstream: fix leaks in unit test; with this, all unit tests are
- Caught by the tinderbox's -Werror=misleading-indentation, ok djm@
+ leak free (as far as valgrind can spot anyway)
- OpenBSD-Commit-ID: d44656af594c3b2366eb87d6abcef83e1c88a6ca
+ OpenBSD-Regress-ID: b824d8b27998365379963440e5d18b95ca03aa17
-commit b59162da99399d89bd57f71c170c0003c55b1583
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Feb 23 15:20:42 2018 +1100
+commit 2f6accff5085eb79b0dbe262d8b85ed017d1a51c
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jul 13 11:39:25 2018 +1000
- Check for ifaddrs.h for BindInterface.
+ Enable leak checks for unit tests with valgrind
- BindInterface required getifaddr and friends so disable if not available
- (eg Solaris 10). We should be able to add support for some systems with
- a bit more work but this gets the building again.
+ Leave the leak checking on unconditionally when running with valgrind.
+ The unit tests are leak-free and I want them to stay that way.
-commit a8dd6fe0aa10b6866830b4688a73ef966f0aed88
+commit e46cfbd9db5e907b821bf4fd0184d4dab99815ee
Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 23 14:19:11 2018 +1100
+Date: Fri Jul 13 11:38:59 2018 +1000
- space before tab in previous
+ increase timeout to match cfgmatch.sh
+
+ lets test pass under valgrind (on my workstation at least)
-commit b5e9263c7704247f9624c8f5c458e9181fcdbc09
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 9 03:40:22 2018 +0000
+commit 6aa1bf475cf3e7a2149acc5a1e80e904749f064c
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Jul 12 14:54:18 2018 +1000
- upstream: Replace fatal with exit in the case that we do not have
-
- $SUDO set. Prevents test failures when neither sudo nor doas are configured.
-
- OpenBSD-Regress-ID: 6a0464decc4f8ac7d6eded556a032b0fc521bc7b
+ rm regress/misc/kexfuzz/*.o in distclean target
-commit 3e9d3192ad43758ef761c5b0aa3ac5ccf8121ef2
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Feb 23 14:10:53 2018 +1100
+commit eef1447ddb559c03725a23d4aa6d03f40e8b0049
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Jul 12 14:49:26 2018 +1000
- Use portable syntax for REGRESSTMP.
+ repair !WITH_OPENSSL build
-commit 73282b61187883a2b2bb48e087fdda1d751d6059
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 23 03:03:00 2018 +0000
+commit 4d3b2f36fd831941d1627ac587faae37b6d3570f
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Jul 12 14:49:14 2018 +1000
- upstream: unbreak interop test after SSHv1 purge; patch from Colin
-
- Watson via bz#2823
-
- OpenBSD-Regress-ID: 807d30a597756ed6612bdf46dfebca74f49cb31a
+ missing headers
-commit f8985dde5f46aedade0373365cbf86ed3f1aead2
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 9 03:42:57 2018 +0000
+commit 3f420a692b293921216549c1099c2e46ff284eae
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Jul 12 14:57:46 2018 +1000
- upstream: Skip sftp-chroot test when SUDO not set instead of
-
- fatal().
+ Remove key.h from portable files too.
- OpenBSD-Regress-ID: cd4b5f1109b0dc09af4e5ea7d4968c43fbcbde88
+ Commit 5467fbcb removed key.h so stop including it in portable files
+ too. Fixes builds on lots of platforms.
-commit df88551c02d4e3445c44ff67ba8757cff718609a
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 9 03:40:22 2018 +0000
+commit e2c4af311543093f16005c10044f7e06af0426f0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jul 12 04:35:25 2018 +0000
- upstream: Replace fatal with exit in the case that we do not have
+ upstream: remove prototype to long-gone function
- $SUDO set. Prevents test failures when neither sudo nor doas are configured.
+ OpenBSD-Commit-ID: 0414642ac7ce01d176b9f359091a66a8bbb640bd
+
+commit 394a842e60674bf8ee5130b9f15b01452a0b0285
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed Jul 11 18:55:11 2018 +0000
+
+ upstream: treat ssh_packet_write_wait() errors as fatal; ok djm@
- OpenBSD-Regress-ID: 6a0464decc4f8ac7d6eded556a032b0fc521bc7b
+ OpenBSD-Commit-ID: f88ba43c9d54ed2d911218aa8d3f6285430629c3
-commit 3b252c20b19f093e87363de197f1100b79705dd3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Feb 8 08:46:20 2018 +0000
+commit 5467fbcb09528ecdcb914f4f2452216c24796790
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed Jul 11 18:53:29 2018 +0000
- upstream: some helpers to check verbose/quiet mode
+ upstream: remove legacy key emulation layer; ok djm@
- OpenBSD-Regress-ID: e736aac39e563f5360a0935080a71d5fdcb976de
+ OpenBSD-Commit-ID: 2b1f9619259e222bbd4fe9a8d3a0973eafb9dd8d
-commit ac2e3026bbee1367e4cda34765d1106099be3287
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 23 02:34:33 2018 +0000
+commit 5dc4c59d5441a19c99e7945779f7ec9051126c25
+Author: martijn@openbsd.org <martijn@openbsd.org>
+Date: Wed Jul 11 08:19:35 2018 +0000
- upstream: Add BindInterface ssh_config directive and -B
+ upstream: s/wuth/with/ in comment
- command-line argument to ssh(1) that directs it to bind its outgoing
- connection to the address of the specified network interface.
-
- BindInterface prefers to use addresses that aren't loopback or link-
- local, but will fall back to those if no other addresses of the
- required family are available on that interface.
-
- Based on patch by Mike Manning in bz#2820, ok dtucker@
-
- OpenBSD-Commit-ID: c5064d285c2851f773dd736a2c342aa384fbf713
+ OpenBSD-Commit-ID: 9de41468afd75f54a7f47809d2ad664aa577902c
-commit fcdb9d777839a3fa034b3bc3067ba8c1f6886679
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 19 00:55:02 2018 +0000
+commit 1c688801e9dd7f9889fb2a29bc2b6fbfbc35a11f
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Wed Jul 11 12:12:38 2018 +1000
- upstream: emphasise that the hostkey rotation may send key types
-
- that the client may not support, and that the client should simply disregard
- such keys (this is what ssh does already).
+ Include stdlib.h for declaration of free.
- OpenBSD-Commit-ID: 65f8ffbc32ac8d12be8f913d7c0ea55bef8622bf
+ Fixes build with -Werror on at least Fedora and probably others.
-commit ce066f688dc166506c082dac41ca686066e3de5f
+commit fccfa239def497615f92ed28acc57cfe63da3666
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Jul 11 10:19:56 2018 +1000
+
+ VALGRIND_CHECK_LEAKS logic was backwards :(
+
+commit 416287d45fcde0a8e66eee8b99aa73bd58607588
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 22 20:45:09 2018 +1100
+Date: Wed Jul 11 10:10:26 2018 +1000
- Add headers for sys/audit.h.
-
- On some older platforms (at least sunos4, probably others) sys/audit.h
- requires some other headers. Patch from klausz at haus-gisela.de.
+ Fix sshbuf_new error path in skey.
-commit 3fd2d2291a695c96a54269deae079bacce6e3fb9
+commit 7aab109b8b90a353c1af780524f1ac0d3af47bab
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Mon Feb 19 18:37:40 2018 +1100
+Date: Wed Jul 11 10:06:18 2018 +1000
- Add REGRESSTMP make var override.
+ Supply missing third arg in skey.
- Defaults to original location ($srcdir/regress) but allows overriding
- if desired, eg a directory in /tmp.
+ During the change to the new buffer api the third arg to
+ sshbuf_get_cstring was ommitted. Fixes build when configured with skey.
-commit f8338428588f3ecb5243c86336eccaa28809f97e
+commit 380320bb72cc353a901790ab04b6287fd335dc4a
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 18 15:53:15 2018 +1100
+Date: Wed Jul 11 10:03:34 2018 +1000
- Remove now-unused check for getrusage.
-
- getrusage was used in ssh-rand-helper but that's now long gone.
- Patch from klauszh at haus-gisela.de.
+ Supply some more missing "int r" in skey
-commit 8570177195f6a4b3173c0a25484a83641ee3faa6
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 16 04:43:11 2018 +0000
+commit d20720d373d8563ee737d1a45dc5e0804d622dbc
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Jul 11 09:56:36 2018 +1000
- upstream: Don't send IUTF8 to servers that don't like them.
-
- Some SSH servers eg "ConfD" drop the connection if the client sends the
- new IUTF8 (RFC8160) terminal mode even if it's not set. Add a bug bit
- for such servers and avoid sending IUTF8 to them. ok djm@
+ disable valgrind memleak checking by default
- OpenBSD-Commit-ID: 26425855402d870c3c0a90491e72e2a8a342ceda
+ Add VALGRIND_CHECK_LEAKS knob to turn it back on.
-commit f6dc2ba3c9d12be53057b9371f5109ec553a399f
+commit 79c9d35018f3a5e30ae437880b669aa8636cd3cd
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Fri Feb 16 17:32:28 2018 +1100
+Date: Wed Jul 11 09:54:00 2018 +1000
- freezero should check for NULL.
+ Supply missing "int r" in skey code.
-commit 680321f3eb46773883111e234b3c262142ff7c5b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 16 02:40:45 2018 +0000
+commit 984bacfaacbbe31c35191b828fb5b5b2f0362c36
+Author: sf@openbsd.org <sf@openbsd.org>
+Date: Tue Jul 10 09:36:58 2018 +0000
- upstream: Mention recent DH KEX methods:
+ upstream: re-remove some pre-auth compression bits
- diffie-hellman-group14-sha256
- diffie-hellman-group16-sha512
- diffie-hellman-group18-sha512
+ This time, make sure to not remove things that are necessary for
+ pre-auth compression on the client. Add a comment that pre-auth
+ compression is still supported in the client.
- From Jakub Jelen via bz#2826
+ ok markus@
- OpenBSD-Commit-ID: 51bf769f06e55447f4bfa7306949e62d2401907a
+ OpenBSD-Commit-ID: 282c6fec7201f18a5c333bbb68d9339734d2f784
-commit 88c50a5ae20902715f0fca306bb9c38514f71679
+commit 120a1ec74e8d9d29f4eb9a27972ddd22351ddef9
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Jul 10 19:39:52 2018 +1000
+
+ Adapt portable to legacy buffer API removal
+
+commit 0f3958c1e6ffb8ea4ba27e2a97a00326fce23246
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 16 02:32:40 2018 +0000
+Date: Tue Jul 10 09:13:30 2018 +0000
- upstream: stop loading DSA keys by default, remove sshd_config
-
- stanza and manpage bits; from Colin Watson via bz#2662, ok dtucker@
+ upstream: kerberos/gssapi fixes for buffer removal
- OpenBSD-Commit-ID: d33a849f481684ff655c140f5eb1b4acda8c5c09
+ OpenBSD-Commit-ID: 1cdf56fec95801e4563c47f21696f04cd8b60c4c
-commit d2b3db2860c962927def39a52f67f1c23f7b201a
-Author: jsing@openbsd.org <jsing@openbsd.org>
-Date: Wed Feb 14 16:27:24 2018 +0000
+commit c74ae8e7c45f325f3387abd48fa7dfef07a08069
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jul 10 06:45:29 2018 +0000
- upstream: Ensure that D mod (P-1) and D mod (Q-1) are calculated in
-
- constant time.
-
- This avoids a potential side channel timing leak.
-
- ok djm@ markus@
+ upstream: buffer.[ch] and bufaux.c are no more
- OpenBSD-Commit-ID: 71ff3c16be03290e63d8edab8fac053d8a82968c
+ OpenBSD-Commit-ID: d1a1852284e554f39525eb4d4891b207cfb3d3a0
-commit 4270efad7048535b4f250f493d70f9acfb201593
-Author: jsing@openbsd.org <jsing@openbsd.org>
-Date: Wed Feb 14 16:03:32 2018 +0000
+commit a881e5a133d661eca923fb0633a03152ab2b70b2
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jul 10 06:43:52 2018 +0000
- upstream: Some obvious freezero() conversions.
-
- This also zeros an ed25519_pk when it was not being zeroed previously.
-
- ok djm@ dtucker@
+ upstream: one mention of Buffer that almost got away :)
- OpenBSD-Commit-ID: 5c196a3c85c23ac0bd9b11bcadaedd90b7a2ce82
+ OpenBSD-Commit-ID: 30d7c27a90b4544ad5dfacf654595710cd499f02
-commit affa6ba67ffccc30b85d6e98f36eb5afd9386882
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 22:32:04 2018 +1100
+commit 49f47e656b60bcd1d1db98d88105295f4b4e600d
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:59:10 2018 +0000
- Remove execute bit from modpipe.c.
+ upstream: replace cast with call to sshbuf_mutable_ptr(); ok djm@
+
+ OpenBSD-Commit-ID: 4dfe9d29fa93d9231645c89084f7217304f7ba29
-commit 9879dca438526ae6dfd656fecb26b0558c29c731
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 22:26:16 2018 +1100
+commit cb30cd47041edb03476be1c8ef7bc1f4b69d1555
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:56:06 2018 +0000
- Update prngd link to point to sourceforge.
+ upstream: remove legacy buffer API emulation layer; ok djm@
+
+ OpenBSD-Commit-ID: 2dd5dc17cbc23195be4299fa93be2707a0e08ad9
-commit b6973fa5152b1a0bafd2417b7c3ad96f6e87d014
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 22:22:38 2018 +1100
+commit 235c7c4e3bf046982c2d8242f30aacffa01073d1
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:53:45 2018 +0000
- Remove references to UNICOS.
+ upstream: sshd: switch monitor to sshbuf API; lots of help & ok
+
+ djm@
+
+ OpenBSD-Commit-ID: d89bd02d33974fd35ca0b8940d88572227b34a48
-commit f1ca487940449f0b64f38f1da575078257609966
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 22:18:37 2018 +1100
+commit b8d9214d969775e409e1408ecdf0d58fad99b344
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:37:55 2018 +0000
- Remove extra newline.
+ upstream: sshd: switch GSSAPI to sshbuf API; ok djm@
+
+ OpenBSD-Commit-ID: e48449ab4be3f006f7ba33c66241b7d652973e30
-commit 6d4e980f3cf27f409489cf89cd46c21501b13731
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 22:16:54 2018 +1100
+commit c7d39ac8dc3587c5f05bdd5bcd098eb5c201c0c8
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:35:50 2018 +0000
- OpenSSH's builtin entropy gathering is long gone.
+ upstream: sshd: switch authentication to sshbuf API; ok djm@
+
+ OpenBSD-Commit-ID: 880aa06bce4b140781e836bb56bec34873290641
-commit 389125b25d1a1d7f22e907463b7e8eca74af79ea
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 21:43:01 2018 +1100
+commit c3cb7790e9efb14ba74b2d9f543ad593b3d55b31
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:29:36 2018 +0000
- Replace remaining mysignal() with signal().
+ upstream: sshd: switch config to sshbuf API; ok djm@
- These seem to have been missed during the replacement of mysignal
- with #define signal in commit 5ade9ab. Both include the requisite
- headers to pick up the #define.
+ OpenBSD-Commit-ID: 72b02017bac7feac48c9dceff8355056bea300bd
-commit 265d88d4e61e352de6791733c8b29fa3d7d0c26d
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 20:06:19 2018 +1100
+commit 2808d18ca47ad3d251836c555f0e22aaca03d15c
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:26:02 2018 +0000
- Remove remaining now-obsolete cvs $Ids.
+ upstream: sshd: switch loginmsg to sshbuf API; ok djm@
+
+ OpenBSD-Commit-ID: f3cb4e54bff15c593602d95cc43e32ee1a4bac42
-commit 015749e9b1d2f6e14733466d19ba72f014d0845c
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 15 17:01:54 2018 +1100
+commit 89dd615b8b531979be63f05f9d5624367c9b28e6
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:20:26 2018 +0000
- Regenerate dependencies after UNICOS removal.
+ upstream: ttymodes: switch to sshbuf API; ok djm@
+
+ OpenBSD-Commit-ID: 5df340c5965e822c9da21e19579d08dea3cbe429
-commit ddc0f3814881ea279a6b6d4d98e03afc60ae1ed7
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 13 09:10:46 2018 +1100
+commit f4608a7065480516ab46214f554e5f853fb7870f
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:18:10 2018 +0000
- Remove UNICOS support.
+ upstream: client: switch mux to sshbuf API; with & ok djm@
- The code required to support it is quite invasive to the mainline
- code that is synced with upstream and is an ongoing maintenance burden.
- Both the hardware and software are literal museum pieces these days and
- we could not find anyone still running OpenSSH on one.
+ OpenBSD-Commit-ID: 5948fb98d704f9c4e075b92edda64e0290b5feb2
-commit 174bed686968494723e6db881208cc4dac0d020f
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 13 18:12:47 2018 +1100
+commit cecee2d607099a7bba0a84803e2325d15be4277b
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 21:03:30 2018 +0000
- Retpoline linker flag only needed for linking.
+ upstream: client: switch to sshbuf API; ok djm@
+
+ OpenBSD-Commit-ID: 60cb0356114acc7625ab85105f6f6a7cd44a8d05
-commit 075e258c2cc41e1d7f3ea2d292c5342091728d40
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 13 17:36:43 2018 +1100
+commit ff55f4ad898137d4703e7a2bcc81167dfe8e9324
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jul 9 20:39:28 2018 +0000
- Default PidFile is sshd.pid not ssh.pid.
+ upstream: pkcs11: switch to sshbuf API; ok djm@
+
+ OpenBSD-Commit-ID: 98cc4e800f1617c51caf59a6cb3006f14492db79
-commit 49f3c0ec47730ea264e2bd1e6ece11167d6384df
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 13 16:27:09 2018 +1100
+commit 168b46f405d6736960ba7930389eecb9b6710b7e
+Author: sf@openbsd.org <sf@openbsd.org>
+Date: Mon Jul 9 13:37:10 2018 +0000
- Remove assigned-to-but-never-used variable.
+ upstream: Revert previous two commits
- 'p' was removed in previous change but I neglected to remove the
- otherwise-unused assignment to it.
+ It turns out we still support pre-auth compression on the client.
+ Therefore revert the previous two commits:
+
+ date: 2018/07/06 09:06:14; author: sf; commitid: yZVYKIRtUZWD9CmE;
+ Rename COMP_DELAYED to COMP_ZLIB
+
+ Only delayed compression is supported nowadays.
+
+ ok markus@
+
+ date: 2018/07/06 09:05:01; author: sf; commitid: rEGuT5UgI9f6kddP;
+ Remove leftovers from pre-authentication compression
+
+ Support for this has been removed in 2016.
+ COMP_DELAYED will be renamed in a later commit.
+
+ ok markus@
+
+ OpenBSD-Commit-ID: cdfef526357e4e1483c86cf599491b2dafb77772
-commit b8bbff3b3fc823bf80c5ab226c94f13cb887d5b1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Feb 13 03:36:56 2018 +0000
+commit ab39267fa1243d02b6c330615539fc4b21e17dc4
+Author: sf@openbsd.org <sf@openbsd.org>
+Date: Fri Jul 6 09:06:14 2018 +0000
- upstream: remove space before tab
+ upstream: Rename COMP_DELAYED to COMP_ZLIB
- OpenBSD-Commit-ID: 674edd214d0a7332dd4623c9cf8117301b012890
+ Only delayed compression is supported nowadays.
+
+ ok markus@
+
+ OpenBSD-Commit-ID: 5b1dbaf3d9a4085aaa10fec0b7a4364396561821
-commit 05046d907c211cb9b4cd21b8eff9e7a46cd6c5ab
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Feb 11 21:16:56 2018 +0000
+commit 95db395d2e56a6f868193aead6cadb2493f036c6
+Author: sf@openbsd.org <sf@openbsd.org>
+Date: Fri Jul 6 09:05:01 2018 +0000
- upstream Don't reset signal handlers inside handlers.
+ upstream: Remove leftovers from pre-authentication compression
- The signal handlers from the original ssh1 code on which OpenSSH
- is based assume unreliable signals and reinstall their handlers.
- Since OpenBSD (and pretty much every current system) has reliable
- signals this is not needed. In the unlikely even that -portable
- is still being used on such systems we will deal with it in the
- compat layer. ok deraadt@
+ Support for this has been removed in 2016.
+ COMP_DELAYED will be renamed in a later commit.
- OpenBSD-Commit-ID: f53a1015cb6908431b92116130d285d71589612c
+ ok markus@
+
+ OpenBSD-Commit-ID: 6a99616c832627157113fcb0cf5a752daf2e6b58
-commit 3c51143c639ac686687c7acf9b373b8c08195ffb
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 13 09:07:29 2018 +1100
+commit f28a4d5cd24c4aa177e96b4f96957991e552cb70
+Author: sf@openbsd.org <sf@openbsd.org>
+Date: Fri Jul 6 09:03:02 2018 +0000
- Whitespace sync with upstream.
+ upstream: Remove unused ssh_packet_start_compression()
+
+ ok markus@
+
+ OpenBSD-Commit-ID: 9d34cf2f59aca5422021ae2857190578187dc2b4
-commit 19edfd4af746bedf0df17f01953ba8c6d3186eb7
+commit 872517ddbb72deaff31d4760f28f2b0a1c16358f
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Tue Feb 13 08:25:46 2018 +1100
+Date: Fri Jul 6 13:32:02 2018 +1000
- Whitespace sync with upstream.
+ Defer setting bufsiz in getdelim.
+
+ Do not write to bufsiz until we are sure the malloc has succeeded,
+ in case any callers rely on it (which they shouldn't). ok djm@
-commit fbfa6f980d7460b3e12b0ce88ed3b6018edf4711
+commit 3deb56f7190a414dc264e21e087a934fa1847283
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 11 21:25:11 2018 +1300
+Date: Thu Jul 5 13:32:01 2018 +1000
- Move signal compat code into bsd-signal.{c,h}
+ Fix other callers of read_environment_file.
+
+ read_environment_file recently gained an extra argument Some platform
+ specific code also calls it so add the argument to those too. Fixes
+ build on Solaris and AIX.
-commit 24d2a33bd3bf5170700bfdd8675498aa09a79eab
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 11 21:20:39 2018 +1300
+commit 314908f451e6b2d4ccf6212ad246fa4619c721d3
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jul 4 13:51:45 2018 +0000
- Include headers for linux/if.h.
+ upstream: deal with API rename: match_filter_list() =>
- Prevents configure-time "present but cannot be compiled" warning.
+ match_filter_blacklist()
+
+ OpenBSD-Regress-ID: 2da342be913efeb51806351af906fab01ba4367f
-commit bc02181c24fc551aab85eb2cff0f90380928ef43
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 11 19:45:47 2018 +1300
+commit 89f54cdf6b9cf1cf5528fd33897f1443913ddfb4
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jul 4 13:51:12 2018 +0000
- Fix test for -z,retpolineplt linker flag.
+ upstream: exercise new expansion behaviour of
+
+ PubkeyAcceptedKeyTypes and, by proxy, test kex_assemble_names()
+
+ ok markus@
+
+ OpenBSD-Regress-ID: 292978902e14d5729aa87e492dd166c842f72736
-commit 3377df00ea3fece5293db85fe63baef33bf5152e
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sun Feb 11 09:32:37 2018 +1100
+commit 187633f24c71564e970681c8906df5a6017dcccf
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jul 3 13:53:26 2018 +0000
- Add checks for Spectre v2 mitigation (retpoline)
+ upstream: add a comment that could have saved me 45 minutes of wild
- This adds checks for gcc and clang flags for mitigations for Spectre
- variant 2, ie "retpoline". It'll automatically enabled if the compiler
- supports it as part of toolchain hardening flag. ok djm@
+ goose chasing
+
+ OpenBSD-Regress-ID: d469b29ffadd3402c090e21b792d627d46fa5297
-commit d9e5cf078ea5380da6df767bb1773802ec557ef0
+commit 312d2f2861a2598ed08587cb6c45c0e98a85408f
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 09:25:34 2018 +0000
+Date: Wed Jul 4 13:49:31 2018 +0000
- upstream commit
+ upstream: repair PubkeyAcceptedKeyTypes (and friends) after RSA
- constify some private key-related functions; based on
- https://github.com/openssh/openssh-portable/pull/56 by Vincent Brillault
+ signature work - returns ability to add/remove/specify algorithms by
+ wildcard.
- OpenBSD-Commit-ID: dcb94a41834a15f4d00275cb5051616fdc4c988c
+ Algorithm lists are now fully expanded when the server/client configs
+ are finalised, so errors are reported early and the config dumps
+ (e.g. "ssh -G ...") now list the actual algorithms selected.
+
+ Clarify that, while wildcards are accepted in algorithm lists, they
+ aren't full pattern-lists that support negation.
+
+ (lots of) feedback, ok markus@
+
+ OpenBSD-Commit-ID: a8894c5c81f399a002f02ff4fe6b4fa46b1f3207
-commit a7c38215d564bf98e8e9eb40c1079e3adf686f15
+commit 303af5803bd74bf05d375c04e1a83b40c30b2be5
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 09:03:54 2018 +0000
+Date: Tue Jul 3 11:43:49 2018 +0000
- upstream commit
-
- Mention ServerAliveTimeout in context of TCPKeepAlives;
- prompted by Christoph Anton Mitterer via github
+ upstream: some magic for RSA-SHA2 checks
- OpenBSD-Commit-ID: f0cf1b5bd3f1fbf41d71c88d75d93afc1c880ca2
+ OpenBSD-Regress-ID: e5a9b11368ff6d86e7b25ad10ebe43359b471cd4
-commit 62562ceae61e4f7cf896566592bb840216e71061
+commit 7d68e262944c1fff1574600fe0e5e92ec8b398f5
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Jul 3 23:27:11 2018 +1000
+
+ depend
+
+commit b4d4eda633af433d20232cbf7e855ceac8b83fe5
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 06:54:38 2018 +0000
+Date: Tue Jul 3 13:20:25 2018 +0000
- upstream commit
+ upstream: some finesse to fix RSA-SHA2 certificate authentication
- clarify IgnoreUserKnownHosts; based on github PR from
- Christoph Anton Mitterer.
+ for certs hosted in ssh-agent
- OpenBSD-Commit-ID: 4fff2c17620c342fb2f1f9c2d2e679aab3e589c3
+ OpenBSD-Commit-ID: e5fd5edd726137dda2d020e1cdebc464110a010f
-commit 4f011daa4cada6450fa810f7563b8968639bb562
+commit d78b75df4a57e0f92295f24298e5f2930e71c172
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 06:40:28 2018 +0000
+Date: Tue Jul 3 13:07:58 2018 +0000
- upstream commit
-
- Shorter, more accurate explanation of
- NoHostAuthenticationForLocalhost without the confusing example. Prompted by
- Christoph Anton Mitterer via github and bz#2293.
+ upstream: check correct variable; unbreak agent keys
- OpenBSD-Commit-ID: 19dc96bea25b80d78d416b581fb8506f1e7b76df
+ OpenBSD-Commit-ID: c36981fdf1f3ce04966d3310826a3e1e6233d93e
-commit 77e05394af21d3f5faa0c09ed3855e4505a5cf9f
+commit 2f30300c5e15929d0e34013f38d73e857f445e12
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 06:15:12 2018 +0000
+Date: Tue Jul 3 11:42:12 2018 +0000
- upstream commit
+ upstream: crank version number to 7.8; needed for new compat flag
- Disable RemoteCommand and RequestTTY in the ssh session
- started by scp. sftp is already doing this. From Camden Narzt via github; ok
- dtucker
+ for prior version; part of RSA-SHA2 strictification, ok markus@
- OpenBSD-Commit-ID: 59e2611141c0b2ee579c6866e8eb9d7d8217bc6b
+ OpenBSD-Commit-ID: 84a11fc0efd2674c050712336b5093f5d408e32b
-commit ca613249a00b64b2eea9f52d3834b55c28cf2862
+commit 4ba0d54794814ec0de1ec87987d0c3b89379b436
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 05:48:46 2018 +0000
+Date: Tue Jul 3 11:39:54 2018 +0000
- upstream commit
+ upstream: Improve strictness and control over RSA-SHA2 signature
- Refuse to create a certificate with an unusable number of
- principals; Prompted by gdestuynder via github
+ In ssh, when an agent fails to return a RSA-SHA2 signature when
+ requested and falls back to RSA-SHA1 instead, retry the signature to
+ ensure that the public key algorithm sent in the SSH_MSG_USERAUTH
+ matches the one in the signature itself.
- OpenBSD-Commit-ID: 8cfae2451e8f07810e3e2546dfdcce66984cbd29
+ In sshd, strictly enforce that the public key algorithm sent in the
+ SSH_MSG_USERAUTH message matches what appears in the signature.
+
+ Make the sshd_config PubkeyAcceptedKeyTypes and
+ HostbasedAcceptedKeyTypes options control accepted signature algorithms
+ (previously they selected supported key types). This allows these
+ options to ban RSA-SHA1 in favour of RSA-SHA2.
+
+ Add new signature algorithms "rsa-sha2-256-cert-v01@openssh.com" and
+ "rsa-sha2-512-cert-v01@openssh.com" to force use of RSA-SHA2 signatures
+ with certificate keys.
+
+ feedback and ok markus@
+
+ OpenBSD-Commit-ID: c6e9f6d45eed8962ad502d315d7eaef32c419dde
-commit b56ac069d46b6f800de34e1e935f98d050731d14
+commit 95344c257412b51199ead18d54eaed5bafb75617
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Feb 10 05:43:26 2018 +0000
+Date: Tue Jul 3 10:59:35 2018 +0000
- upstream commit
+ upstream: allow sshd_config PermitUserEnvironment to accept a
- fatal if we're unable to write all the public key; previously
- we would silently ignore errors writing the comment and terminating newline.
- Prompted by github PR from WillerZ; ok dtucker
+ pattern-list of whitelisted environment variable names in addition to yes|no.
- OpenBSD-Commit-ID: 18fbfcfd4e8c6adbc84820039b64d70906e49831
-
-commit cdb10bd431f9f6833475c27e9a82ebb36fdb12db
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 11:18:38 2018 +1100
+ bz#1800, feedback and ok markus@
+
+ OpenBSD-Commit-ID: 77dc2b468e0bf04b53f333434ba257008a1fdf24
- Add changelog entry for binary strip change.
-
-commit fbddd91897cfaf456bfc2081f39fb4a2208a0ebf
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 11:14:54 2018 +1100
-
- Remove unused variables.
-
-commit 937d96587df99c16c611d828cded292fa474a32b
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 11:12:45 2018 +1100
+commit 6f56fe4b9578b0627667f8bce69d4d938a88324c
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Tue Jun 26 11:23:59 2018 +0000
- Don't strip binaries so debuginfo gets built.
+ upstream: Fix "WARNING: line 6 disappeared in /etc/moduli, giving up"
- Tell install not to strip binaries during package creation so that the
- debuginfo package can be built.
-
-commit eb0865f330f59c889ec92696b97bd397090e720c
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 10:33:11 2018 +1100
-
- Fix bogus dates in changelog.
-
-commit 7fbde1b34c1f6c9ca9e9d10805ba1e5e4538e165
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 10:25:15 2018 +1100
-
- Remove SSH1 from description.
-
-commit 9c34a76f099c4e0634bf6ecc2f40ce93925402c4
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 10:19:16 2018 +1100
-
- Add support for compat-openssl10 build dep.
+ when choosing a prime. An extra increment of linenum snuck in as part of the
+ conversion to getline(). OK djm@ markus@
+
+ OpenBSD-Commit-ID: 0019225cb52ed621b71cd9f19ee2e78e57e3dd38
-commit 04f4e8193cb5a5a751fcc356bd6656291fec539e
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 09:57:04 2018 +1100
+commit 1eee79a11c1b3594f055b01e387c49c9a6e80005
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Jul 2 14:13:30 2018 +0000
- Add leading zero so it'll work when rhel not set.
+ upstream: One ampersand is enough to backgroud an process. OpenBSD
- When rhel is not set it will error out with "bad if". Add leading zero
- as per https://fedoraproject.org/wiki/Packaging:DistTag so it'll work
- on non-RHEL.
+ doesn't seem to mind, but some platforms in -portable object to the second.
+
+ OpenBSD-Regress-ID: d6c3e404871764343761dc25c3bbe29c2621ff74
-commit 12abd67a6af28476550807a443b38def2076bb92
+commit 6301e6c787d4e26bfae1119ab4f747bbcaa94e44
Author: Darren Tucker <dtucker@dtucker.net>
-Date: Sat Feb 10 09:56:34 2018 +1100
-
- Update openssl-devel dependency.
-
-commit b33e7645f8813719d7f9173fef24463c8833ebb3
-Author: nkadel <nkadel@gmail.com>
-Date: Sun Nov 16 18:19:58 2014 -0500
+Date: Mon Jul 2 21:16:58 2018 +1000
- Add mandir with-mandir' for RHEL 5 compatibility.
+ Add implementation of getline.
- Activate '--mandir' and '--with-mandir' settings in setup for RHEL
- 5 compatibility.
+ Add getline for the benefit of platforms that don't have it. Sourced
+ from NetBSD (OpenBSD's implementation is a little too chummy with the
+ internals of FILE).
-commit 94f8bf360eb0162e39ddf39d69925c2e93511e40
-Author: nkadel <nkadel@gmail.com>
-Date: Sun Nov 16 18:18:51 2014 -0500
+commit 84623e0037628f9992839063151f7a9f5f13099a
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jun 26 02:02:36 2018 +0000
- Discard 'K5DIR' reporting.
+ upstream: whitespace
- It does not work inside 'mock' build environment.
-
-commit bb7e54dbaf34b70b3e57acf7982f3a2136c94ee5
-Author: nkadel <nkadel@gmail.com>
-Date: Sun Nov 16 18:17:15 2014 -0500
-
- Add 'dist' to 'rel' for OS specific RPM names.
-
-commit 87346f1f57f71150a9b8c7029d8c210e27027716
-Author: nkadel <nkadel@gmail.com>
-Date: Sun Nov 16 14:17:38 2014 -0500
-
- Add openssh-devel >= 0.9.8f for redhat spec file.
+ OpenBSD-Commit-ID: 9276951caf4daf555f6d262e95720e7f79244572
-commit bec1478d710866d3c1b119343a35567a8fc71ec3
-Author: nkadel <nkadel@gmail.com>
-Date: Sun Nov 16 13:10:24 2014 -0500
+commit 90e51d672711c19a36573be1785caf35019ae7a8
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jun 25 22:28:33 2018 +0000
- Enhance BuildRequires for openssh-x11-askpass.
+ upstream: fix NULL dereference in open_listen_match_tcpip()
+
+ OpenBSD-Commit-ID: c968c1d29e392352383c0f9681fcc1e93620c4a9
-commit 3104fcbdd3c70aefcb0cdc3ee24948907db8dc8f
-Author: nkadel <nkadel@gmail.com>
-Date: Sun Nov 16 13:04:14 2014 -0500
+commit f535ff922a67d9fcc5ee69d060d1b21c8bb01d14
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue Jun 19 05:36:57 2018 +0000
- Always include x11-ssh-askpass SRPM.
+ upstream: spelling;
- Always include x11-ssh-askpass tarball in redhat SRPM, even if unused.
+ OpenBSD-Commit-ID: db542918185243bea17202383a581851736553cc
-commit c61d0d038d58eebc365f31830be6e04ce373ad1b
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Feb 10 09:43:12 2018 +1100
+commit 80e199d6175904152aafc5c297096c3e18297691
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jun 19 03:02:17 2018 +0000
- this is long unused; prompted by dtucker@
+ upstream: test PermitListen with bare port numbers
+
+ OpenBSD-Regress-ID: 4b50a02dfb0ccaca08247f3877c444126ba901b3
-commit 745771fb788e41bb7cdad34e5555bf82da3af7ed
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 9 02:37:36 2018 +0000
+commit 87ddd676da0f3abd08b778b12b53b91b670dc93c
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Jun 19 02:59:41 2018 +0000
- upstream commit
+ upstream: allow bare port numbers to appear in PermitListen directives,
- Remove unused sKerberosTgtPassing from enum. From
- calestyo via github pull req #11, ok djm@
+ e.g.
- OpenBSD-Commit-ID: 1008f8870865a7c4968b7aed402a0a9e3e5b9540
-
-commit 1f385f55332db830b0ae22a7663b98279ca2d657
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Feb 8 04:12:32 2018 +0000
-
- upstream commit
+ PermitListen 2222 8080
- Rename struct umac_ctx to umac128_ctx too. In portable
- some linkers complain about two symbols with the same name having differing
- sizes. ok djm@
+ is equivalent to:
- OpenBSD-Commit-ID: cbebf8bdd3310a9795b4939a1e112cfe24061ca3
+ PermitListen *:2222 *:8080
+
+ Some bonus manpage improvements, mostly from markus@
+
+ "looks fine" markus@
+
+ OpenBSD-Commit-ID: 6546b0cc5aab7f53d65ad0a348ca0ae591d6dd24
-commit f1f047fb031c0081dbc8738f05bf5d4cc47acadf
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Feb 7 22:52:45 2018 +0000
+commit 26f96ca10ad0ec5da9b05b99de1e1ccea15a11be
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 15 07:01:11 2018 +0000
- upstream commit
+ upstream: invalidate supplemental group cache used by
- ssh_free checks for and handles NULL args, remove NULL
- checks from remaining callers. ok djm@
+ temporarily_use_uid() when the target uid differs; could cause failure to
+ read authorized_keys under some configurations. patch by Jakub Jelen via
+ bz2873; ok dtucker, markus
- OpenBSD-Commit-ID: bb926825c53724c069df68a93a2597f9192f7e7b
+ OpenBSD-Commit-ID: 48a345f0ee90f6c465a078eb5e89566b23abd8a1
-commit aee49b2a89b6b323c80dd3b431bd486e51f94c8c
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Thu Feb 8 12:36:22 2018 +1100
+commit 89a85d724765b6b82e0135ee5a1181fdcccea9c6
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Jun 10 23:45:41 2018 +0000
- Set SO_REUSEADDR in regression test netcat.
+ upstream: unbreak SendEnv; patch from tb@
- Sometimes multiplex tests fail on Solaris with "netcat: local_listen:
- Address already in use" which is likely due to previous invocations
- leaving the port in TIME_WAIT. Set SO_REUSEADDR (in addition to
- SO_REUSEPORT which is alread set on platforms that support it). ok djm@
+ OpenBSD-Commit-ID: fc808daced813242563b80976e1478de95940056
-commit 1749991c55bab716877b7c687cbfbf19189ac6f1
-Author: jsing@openbsd.org <jsing@openbsd.org>
-Date: Wed Feb 7 05:17:56 2018 +0000
+commit acf4260f0951f89c64e1ebbc4c92f451768871ad
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Jun 9 06:36:31 2018 +0000
- upstream commit
+ upstream: sort previous;
- Convert some explicit_bzero()/free() calls to freezero().
+ OpenBSD-Commit-ID: 27d80d8b8ca99bc33971dee905e8ffd0053ec411
+
+commit 1678d4236451060b735cb242d2e26e1ac99f0947
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 9 03:18:11 2018 +0000
+
+ upstream: slightly better wording re handing of $TERM, from Jakub
- ok deraadt@ dtucker@
+ Jelen via bz2386
- OpenBSD-Commit-ID: f566ab99149650ebe58b1d4b946ea726c3829609
+ OpenBSD-Commit-ID: 14bea3f069a93c8be66a7b97794255a91fece964
-commit 94ec2b69d403f4318b7a0d9b17f8bc3efbf4d0d2
-Author: jsing@openbsd.org <jsing@openbsd.org>
-Date: Wed Feb 7 05:15:49 2018 +0000
+commit 28013759f09ed3ebf7e8335e83a62936bd7a7f47
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 9 03:03:10 2018 +0000
- upstream commit
-
- Remove some #ifdef notyet code from OpenSSL 0.9.8 days.
+ upstream: add a SetEnv directive for sshd_config to allow an
- These functions have never appeared in OpenSSL and are likely never to do
- so.
+ administrator to explicitly specify environment variables set in sessions
+ started by sshd. These override the default environment and any variables set
+ by user configuration (PermitUserEnvironment, etc), but not the SSH_*
+ variables set by sshd itself.
- "kill it with fire" djm@
+ ok markus@
- OpenBSD-Commit-ID: fee9560e283fd836efc2631ef381658cc673d23e
+ OpenBSD-Commit-ID: b6a96c0001ccd7dd211df6cae9e961c20fd718c0
-commit 7cd31632e3a6607170ed0c9ed413a7ded5b9b377
-Author: jsing@openbsd.org <jsing@openbsd.org>
-Date: Wed Feb 7 02:06:50 2018 +0000
+commit 7082bb58a2eb878d23ec674587c742e5e9673c36
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 9 03:01:12 2018 +0000
- upstream commit
+ upstream: add a SetEnv directive to ssh_config that allows setting
- Remove all guards for calls to OpenSSL free functions -
- all of these functions handle NULL, from at least OpenSSL 1.0.1g onwards.
+ environment variables for the remote session (subject to the server accepting
+ them)
- Prompted by dtucker@ asking about guards for RSA_free(), when looking at
- openssh-portable pr#84 on github.
+ refactor SendEnv to remove the arbitrary limit of variable names.
- ok deraadt@ dtucker@
+ ok markus@
- OpenBSD-Commit-ID: 954f1c51b94297d0ae1f749271e184141e0cadae
+ OpenBSD-Commit-ID: cfbb00d9b0e10c1ffff1d83424351fd961d1f2be
-commit 3c000d57d46882eb736c6563edfc4995915c24a2
-Author: Darren Tucker <dtucker@dtucker.net>
-Date: Wed Feb 7 09:19:38 2018 +1100
+commit 3b9798bda15bd3f598f5ef07595d64e23504da91
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 9 02:58:02 2018 +0000
- Remove obsolete "Smartcard support" message
+ upstream: reorder child environment preparation so that variables
- The configure checks that populated $SCARD_MSG were removed in commits
- 7ea845e4 and d8f60022 when the smartcard support was replaced with
- PKCS#11.
+ read from ~/.ssh/environment (if enabled) do not override SSH_* variables set
+ by the server.
+
+ OpenBSD-Commit-ID: 59f9d4c213cdcef2ef21f4b4ae006594dcf2aa7a
-commit 3e615090de0ce36a833d811e01c28aec531247c4
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Feb 6 06:01:54 2018 +0000
+commit 0368889f82f63c82ff8db9f8c944d89e7c657db4
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 8 03:35:36 2018 +0000
- upstream commit
+ upstream: fix incorrect expansion of %i in
- Replace "trojan horse" with the correct term (MITM).
- From maikel at predikkta.com via bz#2822, ok markus@
+ load_public_identity_files(); reported by Roumen Petrov
- OpenBSD-Commit-ID: e86ac64c512057c89edfadb43302ac0aa81a6c53
+ OpenBSD-Commit-ID: a827289e77149b5e0850d72a350c8b0300e7ef25
-commit 3484380110d437c50e17f87d18544286328c75cb
-Author: tb@openbsd.org <tb@openbsd.org>
-Date: Mon Feb 5 05:37:46 2018 +0000
+commit 027607fc2db6a0475a3380f8d95c635482714cb0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 8 01:55:40 2018 +0000
- upstream commit
-
- Add a couple of non-negativity checks to avoid close(-1).
+ upstream: fix some over-long lines and __func__ up some debug
- ok djm
+ messages
- OpenBSD-Commit-ID: 4701ce0b37161c891c838d0931305f1d37a50880
+ OpenBSD-Commit-ID: c70a60b4c8207d9f242fc2351941ba50916bb267
-commit 5069320be93c8b2a6584b9f944c86f60c2b04e48
-Author: tb@openbsd.org <tb@openbsd.org>
-Date: Mon Feb 5 05:36:49 2018 +0000
+commit 6ff6fda705bc204456a5fa12518dde6e8790bb02
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Thu Jun 7 11:26:14 2018 +0000
- upstream commit
+ upstream: tweak previous;
- The file descriptors for socket, stdin, stdout and stderr
- aren't necessarily distinct, so check if they are the same to avoid closing
- the same fd several times.
+ OpenBSD-Commit-ID: f98f16af10b28e24bcecb806cb71ea994b648fd6
+
+commit f2c06ab8dd90582030991f631a2715216bf45e5a
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Jun 8 17:43:36 2018 +1000
+
+ Remove ability to override $LD.
- ok djm
+ Since autoconf always uses $CC to link C programs, allowing users to
+ override LD caused mismatches between what LD_LINK_IFELSE thought worked
+ and what ld thought worked. If you do need to do this kind of thing you
+ need to set a compiler flag such as gcc's -fuse-ld in LDFLAGS.
+
+commit e1542a80797b4ea40a91d2896efdcc76a57056d2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Jun 8 13:55:59 2018 +1000
+
+ Better detection of unsupported compiler options.
- OpenBSD-Commit-ID: 60d71fd22e9a32f5639d4ba6e25a2f417fc36ac1
+ Should prevent "unsupported -Wl,-z,retpoline" warnings during linking.
+ ok djm@
-commit 2b428f90ea1b21d7a7c68ec1ee334253b3f9324d
+commit 57379dbd013ad32ee3f9989bf5f5741065428360
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 5 04:02:53 2018 +0000
+Date: Thu Jun 7 14:29:43 2018 +0000
- upstream commit
-
- I accidentially a word
+ upstream: test the correct configuration option name
- OpenBSD-Commit-ID: 4547ee713fa941da861e83ae7a3e6432f915e14a
+ OpenBSD-Regress-ID: 492279ea9f65657f97a970e0e7c7fd0b339fee23
-commit 130283d5c2545ff017c2162dc1258c5354e29399
+commit 6d41815e202fbd6182c79780b6cc90e1ec1c9981
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jan 25 03:34:43 2018 +0000
+Date: Thu Jun 7 09:26:42 2018 +0000
- upstream commit
-
- certificate options are case-sensitive; fix case on one
- that had it wrong.
+ upstream: some permitlisten fixes from markus@ that I missed in my
- move a badly-place sentence to a less bad place
+ insomnia-fueled commits last night
- OpenBSD-Commit-ID: 231e516bba860699a1eece6d48532d825f5f747b
+ OpenBSD-Commit-ID: 26f23622e928996086e85b1419cc1c0f136e359c
-commit 89f09ee68730337015bf0c3f138504494a34e9a6
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 24 12:20:44 2018 +1100
+commit 4319f7a868d86d435fa07112fcb6153895d03a7f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jun 7 04:46:34 2018 +0000
- crypto_api.h needs includes.h
+ upstream: permitlisten/PermitListen unit test from Markus
+
+ OpenBSD-Regress-ID: ab12eb42f0e14926980441cf7c058a6d1d832ea5
-commit c9c1bba06ad1c7cad8548549a68c071bd807af60
-Author: stsp@openbsd.org <stsp@openbsd.org>
-Date: Tue Jan 23 20:00:58 2018 +0000
+commit fa09076410ffc2d34d454145af23c790d728921e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jun 7 04:31:51 2018 +0000
- upstream commit
+ upstream: fix regression caused by recent permitlisten option commit:
- Fix a logic bug in sshd_exchange_identification which
- prevented clients using major protocol version 2 from connecting to the
- server. ok millert@
+ authorized_keys lines that contained permitopen/permitlisten were being
+ treated as invalid.
- OpenBSD-Commit-ID: 8668dec04586e27f1c0eb039ef1feb93d80a5ee9
+ OpenBSD-Commit-ID: 7ef41d63a5a477b405d142dc925b67d9e7aaa31b
-commit a60c5dcfa2538ffc94dc5b5adb3db5b6ed905bdb
-Author: stsp@openbsd.org <stsp@openbsd.org>
-Date: Tue Jan 23 18:33:49 2018 +0000
+commit 7f90635216851f6cb4bf3999e98b825f85d604f8
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed Jun 6 18:29:18 2018 +0000
- upstream commit
+ upstream: switch config file parsing to getline(3) as this avoids
- Add missing braces; fixes 'write: Socket is not
- connected' error in ssh. ok deraadt@
+ static limits noted by gerhard@; ok dtucker@, djm@
- OpenBSD-Commit-ID: db73a3a9e147722d410866cac34d43ed52e1ad24
-
-commit 20d53ac283e1c60245ea464bdedd015ed9b38f4a
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 23 16:49:43 2018 +1100
-
- rebuild depends
-
-commit 552ea155be44f9c439c1f9f0c38f9e593428f838
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Jan 23 16:49:22 2018 +1100
-
- one SSH_BUG_BANNER instance that got away
+ OpenBSD-Commit-ID: 6d702eabef0fa12e5a1d75c334a8c8b325298b5c
-commit 14b5c635d1190633b23ac3372379517fb645b0c2
+commit 392db2bc83215986a91c0b65feb0e40e7619ce7e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 23 05:27:21 2018 +0000
+Date: Wed Jun 6 18:25:33 2018 +0000
- upstream commit
-
- Drop compatibility hacks for some ancient SSH
- implementations, including ssh.com <=2.* and OpenSSH <= 3.*.
-
- These versions were all released in or before 2001 and predate the
- final SSH RFCs. The hacks in question aren't necessary for RFC-
- compliant SSH implementations.
-
- ok markus@
+ upstream: regress test for PermitOpen
- OpenBSD-Commit-ID: 4be81c67db57647f907f4e881fb9341448606138
+ OpenBSD-Regress-ID: ce8b5f28fc039f09bb297fc4a92319e65982ddaf
-commit 7c77991f5de5d8475cbeb7cbb06d0c7d1611d7bb
+commit 803d896ef30758135e2f438bdd1a0be27989e018
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 23 05:17:04 2018 +0000
+Date: Wed Jun 6 18:24:15 2018 +0000
- upstream commit
-
- try harder to preserve errno during
- ssh_connect_direct() to make the final error message possibly accurate;
- bz#2814, ok dtucker@
+ upstream: man bits for permitlisten authorized_keys option
- OpenBSD-Commit-ID: 57de882cb47381c319b04499fef845dd0c2b46ca
+ OpenBSD-Commit-ID: 86910af8f781a4ac5980fea125442eb25466dd78
-commit 9e9c4a7e57b96ab29fe6d7545ed09d2e5bddbdec
+commit 04df43208b5b460d7360e1598f876b92a32f5922
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 23 05:12:12 2018 +0000
+Date: Wed Jun 6 18:24:00 2018 +0000
- upstream commit
-
- unbreak support for clients that advertise a protocol
- version of "1.99" (indicating both v2 and v1 support). Busted by me during
- SSHv1 purge in r1.358; bz2810, ok dtucker
+ upstream: man bits for PermitListen
- OpenBSD-Commit-ID: e8f9c2bee11afc16c872bb79d6abe9c555bd0e4b
+ OpenBSD-Commit-ID: 35b200cba4e46a16a4db6a80ef11838ab0fad67c
-commit fc21ea97968264ad9bb86b13fedaaec8fd3bf97d
+commit 93c06ab6b77514e0447fe4f1d822afcbb2a9be08
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 23 05:06:25 2018 +0000
+Date: Wed Jun 6 18:23:32 2018 +0000
- upstream commit
-
- don't attempt to force hostnames that are addresses to
- lowercase, but instead canonicalise them through getnameinfo/getaddrinfo to
- remove ambiguities (e.g. ::0001 => ::1) before they are matched against
- known_hosts; bz#2763, ok dtucker@
+ upstream: permitlisten option for authorized_keys; ok markus@
- OpenBSD-Commit-ID: ba0863ff087e61e5c65efdbe53be3cb92c9aefa0
+ OpenBSD-Commit-ID: 8650883018d7aa893173d703379e4456a222c672
-commit d6364f6fb1a3d753d7ca9bf15b2adce961324513
+commit 115063a6647007286cc8ca70abfd2a7585f26ccc
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 23 05:01:15 2018 +0000
+Date: Wed Jun 6 18:22:41 2018 +0000
- upstream commit
+ upstream: Add a PermitListen directive to control which server-side
- avoid modifying pw->pw_passwd; let endpwent() clean up
- for us, but keep a scrubbed copy; bz2777, ok dtucker@
+ addresses may be listened on when the client requests remote forwarding (ssh
+ -R).
- OpenBSD-Commit-ID: 715afc0f59c6b82c4929a73279199ed241ce0752
-
-commit a69bbb07cd6fb4dfb9bdcacd370ab26d0a2b4215
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Sat Jan 13 00:24:09 2018 +0000
-
- upstream commit
+ This is the converse of the existing PermitOpen directive and this
+ includes some refactoring to share much of its implementation.
- clarify authorship; prodded by and ok markus@
+ feedback and ok markus@
- OpenBSD-Commit-ID: e1938eee58c89b064befdabe232835fa83bb378c
+ OpenBSD-Commit-ID: 15a931238c61a3f2ac74ea18a98c933e358e277f
-commit 04214b30be3d3e73a01584db4e040d5ccbaaddd4
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 8 15:37:21 2018 +0000
+commit 7703ae5f5d42eb302ded51705166ff6e19c92892
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Wed Jun 6 16:04:29 2018 +1000
- upstream commit
-
- group shared source files (e.g. SRCS_KEX) and allow
- compilation w/o OPENSSL ok djm@
+ Use ssh-keygen -A to generate missing host keys.
- OpenBSD-Commit-ID: fa728823ba21c4b45212750e1d3a4b2086fd1a62
+ Instead of testing for each specific key type, use ssh-keygen -A to
+ generate any missing host key types.
-commit 25cf9105b849932fc3b141590c009e704f2eeba6
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 8 15:21:49 2018 +0000
+commit e8d59fef1098e24f408248dc64e5c8efa5d01f3c
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Jun 1 06:23:10 2018 +0000
- upstream commit
+ upstream: add missing punctuation after %i in ssh_config.5, and
- move subprocess() so scp/sftp do not need uidswap.o; ok
- djm@
+ make the grammatical format in sshd_config.5 match that in ssh_config.5;
- OpenBSD-Commit-ID: 6601b8360388542c2e5fef0f4085f8e54750bea8
+ OpenBSD-Commit-ID: e325663b9342f3d556e223e5306e0d5fa1a74fa0
-commit b0d34132b3ca26fe94013f01d7b92101e70b68bb
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 8 15:18:46 2018 +0000
+commit a1f737d6a99314e291a87856122cb4dbaf64c641
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Jun 1 05:52:26 2018 +0000
- upstream commit
-
- switch ssh-pkcs11-helper to new API; ok djm@
+ upstream: oops - further adjustment to text neccessary;
- OpenBSD-Commit-ID: e0c0ed2a568e25b1d2024f3e630f3fea837c2a42
+ OpenBSD-Commit-ID: 23585576c807743112ab956be0fb3c786bdef025
-commit ec4a9831184c0c6ed5f7f0cfff01ede5455465a3
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 8 15:15:36 2018 +0000
+commit 294028493471e0bd0c7ffe55dc0c0a67cba6ec41
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Jun 1 05:50:18 2018 +0000
- upstream commit
+ upstream: %U needs to be escaped; tweak text;
- split client/server kex; only ssh-keygen needs
- uuencode.o; only scp/sftp use progressmeter.o; ok djm@
+ OpenBSD-Commit-ID: 30887b73ece257273fb619ab6f4e86dc92ddc15e
+
+commit e5019da3c5a31e6e729a565f2b886a80c4be96cc
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jun 1 04:31:48 2018 +0000
+
+ upstream: Apply umask to all incoming files and directories not
- OpenBSD-Commit-ID: f2c9feb26963615c4fece921906cf72e248b61ee
+ just files. This makes sure it gets applied to directories too, and prevents
+ a race where files get chmodded after creation. bz#2839, ok djm@
+
+ OpenBSD-Commit-ID: 3168ee6c7c39093adac4fd71039600cfa296203b
-commit ec77efeea06ac62ee1d76fe0b3225f3000775a9e
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 8 15:15:17 2018 +0000
+commit a1dcafc41c376332493b9385ee39f9754dc145ec
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 1 03:52:37 2018 +0000
- upstream commit
+ upstream: Adapt to extra default verboisity from ssh-keygen when
- only ssh-keygen needs uuencode.o; only scp/sftp use
- progressmeter.o
+ searching for and hashing known_hosts entries in a single operation
+ (ssh-keygen -HF ...) Patch from Anton Kremenetsky
- OpenBSD-Commit-ID: a337e886a49f96701ccbc4832bed086a68abfa85
+ OpenBSD-Regress-ID: 519585a4de35c4611285bd6a7272766c229b19dd
-commit 25aae35d3d6ee86a8c4c0b1896acafc1eab30172
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Mon Jan 8 15:14:44 2018 +0000
+commit 76f314c75dffd4a55839d50ee23622edad52c168
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue May 22 00:22:49 2018 +0000
- upstream commit
+ upstream: Add TEST_SSH_FAIL_FATAL variable, to force all failures
- uuencode.h is not used
+ to instantly abort the test. Useful in capturing clean logs for individual
+ failure cases.
- OpenBSD-Commit-ID: 238eb4659f3c119904326b9e94a5e507a912796c
+ OpenBSD-Regress-ID: feba18cf338c2328b9601bd4093cabdd9baa3af1
-commit 4f29309c4cb19bcb1774931db84cacc414f17d29
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Jan 3 19:50:43 2018 +1100
+commit 065c8c055df8d83ae7c92e5e524a579d87668aab
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri May 11 03:51:06 2018 +0000
- unbreak fuzz harness
+ upstream: Clean up comment.
+
+ OpenBSD-Regress-ID: 6adb35f384d447e7dcb9f170d4f0d546d3973e10
-commit f6b50bf84dc0b61f22c887c00423e0ea7644e844
+commit 01b048c8eba3b021701bd0ab26257fc82903cba8
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 21 05:46:35 2017 +0000
+Date: Fri Jun 1 04:21:29 2018 +0000
- upstream commit
+ upstream: whitespace
- another libssh casualty
+ OpenBSD-Commit-ID: e5edb5e843ddc9b73a8e46518899be41d5709add
+
+commit 854ae209f992465a276de0b5f10ef770510c2418
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 1 04:05:29 2018 +0000
+
+ upstream: make ssh_remote_ipaddr() capable of being called after
- OpenBSD-Regress-ID: 839b970560246de23e7c50215095fb527a5a83ec
+ the ssh->state has been torn down; bz#2773
+
+ OpenBSD-Commit-ID: 167f12523613ca3d16d7716a690e7afa307dc7eb
-commit 5fb4fb5a0158318fb8ed7dbb32f3869bbf221f13
+commit 3e088aaf236ef35beeef3c9be93fd53700df5861
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 21 03:01:49 2017 +0000
+Date: Fri Jun 1 03:51:34 2018 +0000
- upstream commit
+ upstream: return correct exit code when searching for and hashing
- missed one (unbreak after ssh/lib removal)
+ known_hosts entries in a single operation (ssh-keygen -HF hostname); bz2772
+ Report and fix from Anton Kremenetsky
- OpenBSD-Regress-ID: cfdd132143131769e2d2455e7892b5d55854c322
+ OpenBSD-Commit-ID: ac10ca13eb9bb0bc50fcd42ad11c56c317437b58
-commit e6c4134165d05447009437a96e7201276688807f
+commit 9c935dd9bf05628826ad2495d3e8bdf3d3271c21
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 21 00:41:22 2017 +0000
+Date: Fri Jun 1 03:33:53 2018 +0000
- upstream commit
+ upstream: make UID available as a %-expansion everywhere that the
- unbreak unit tests after removal of src/usr.bin/ssh/lib
+ username is available currently. In the client this is via %i, in the server
+ %U (since %i was already used in the client in some places for this, but used
+ for something different in the server); bz#2870, ok dtucker@
- OpenBSD-Regress-ID: 3a79760494147b20761cbd2bd5c20e86c63dc8f9
+ OpenBSD-Commit-ID: c7e912b0213713316cb55db194b3a6415b3d4b95
-commit d45d69f2a937cea215c7f0424e5a4677b6d8c7fe
+commit d8748b91d1d6c108c0c260ed41fa55f37b9ef34b
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Dec 21 00:00:28 2017 +0000
+Date: Fri Jun 1 03:11:49 2018 +0000
- upstream commit
+ upstream: prefer argv0 to "ssh" when re-executing ssh for ProxyJump
- revert stricter key type / signature type checking in
- userauth path; too much software generates inconsistent messages, so we need
- a better plan.
+ directive; bz2831, feedback and ok dtucker@
- OpenBSD-Commit-ID: 4a44ddc991c803c4ecc8f1ad40e0ab4d22e1c519
+ OpenBSD-Commit-ID: 3cec709a131499fbb0c1ea8a0a9e0b0915ce769e
-commit c5a6cbdb79752f7e761074abdb487953ea6db671
+commit fbb4b5fd4f8e0bb89732670a01954e18b69e15ba
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Dec 19 00:49:30 2017 +0000
+Date: Fri May 25 07:11:01 2018 +0000
- upstream commit
+ upstream: Do not ban PTY allocation when a sshd session is restricted
- explicitly test all key types and their certificate
- counterparts
+ because the user password is expired as it breaks password change dialog.
- refactor a little
+ regression in openssh-7.7 reported by Daniel Wagner
- OpenBSD-Regress-ID: e9ecd5580821b9ef8b7106919c6980d8e45ca8c4
+ OpenBSD-Commit-ID: 9fc09c584c6f1964b00595e3abe7f83db4d90d73
-commit f689adb7a370b5572612d88be9837ca9aea75447
+commit f6a59a22b0c157c4c4e5fd7232f868138223be64
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri May 25 04:25:46 2018 +0000
+
+ upstream: Fix return value confusion in several functions (readdir,
+
+ download and fsync). These should return -1 on error, not a sftp status code.
+
+ patch from Petr Cerny in bz#2871
+
+ OpenBSD-Commit-ID: 651aa0220ad23c9167d9297a436162d741f97a09
+
+commit 1da5934b860ac0378d52d3035b22b6670f6a967e
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Dec 11 11:41:56 2017 +0000
+Date: Fri May 25 03:20:59 2018 +0000
- upstream commit
+ upstream: If select() fails in ssh_packet_read_seqnr go directly to
- use cmp in a loop instead of diff -N to compare
- directories. The former works on more platforms for Portable.
+ the error path instead of trying to read from the socket on the way out,
+ which resets errno and causes the true error to be misreported. ok djm@
- OpenBSD-Regress-ID: c3aa72807f9c488e8829a26ae50fe5bcc5b57099
+ OpenBSD-Commit-ID: 2614edaadbd05a957aa977728aa7a030af7c6f0a
-commit 748dd8e5de332b24c40f4b3bbedb902acb048c98
+commit 4ef75926ef517d539f2c7aac3188b09f315c86a7
Author: Damien Miller <djm@mindrot.org>
-Date: Tue Dec 19 16:17:59 2017 +1100
+Date: Fri May 25 13:36:58 2018 +1000
- remove blocks.c from Makefile
+ Permit getuid()/geteuid() syscalls.
+
+ Requested for Linux/s390; patch from Eduardo Barretto via bz#2752;
+ ok dtucker
-commit 278856320520e851063b06cef6ef1c60d4c5d652
+commit 4b22fd8ecefd059a66140be67f352eb6145a9d88
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Dec 19 00:24:34 2017 +0000
+Date: Tue May 22 00:13:26 2018 +0000
- upstream commit
+ upstream: support ProxyJump=none to disable ProxyJump
- include signature type and CA key (if applicable) in some
- debug messages
+ functionality; bz#2869 ok dtucker@
- OpenBSD-Commit-ID: b71615cc20e78cec7105bb6e940c03ce9ae414a5
+ OpenBSD-Commit-ID: 1c06ee08eb78451b5837fcfd8cbebc5ff3a67a01
-commit 7860731ef190b52119fa480f8064ab03c44a120a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 18 23:16:23 2017 +0000
+commit f41bcd70f55b4f0fc4d8e1039cb361ac922b23fb
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 15 05:40:11 2018 +0000
- upstream commit
+ upstream: correct keyowrd name (permitemptypasswords); from brendan
- unbreak hostkey rotation; attempting to sign with a
- desired signature algorithm of kex->hostkey_alg is incorrect when the key
- type isn't capable of making those signatures. ok markus@
+ macdonell
- OpenBSD-Commit-ID: 35ae46864e1f5859831ec0d115ee5ea50953a906
+ OpenBSD-Commit-ID: ef1bdbc936b2ea693ee37a4c20a94d4d43f5fda3
-commit 966ef478339ad5e631fb684d2a8effe846ce3fd4
+commit f18bc97151340127859634d20d79fd39ec8a7f39
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 18 23:14:34 2017 +0000
+Date: Fri May 11 04:01:11 2018 +0000
- upstream commit
+ upstream: Emphasise that -w implicitly sets Tunnel=point-to-point
- log mismatched RSA signature types; ok markus@
+ and that users should specify an explicit Tunnel directive if they don't want
+ this. bz#2365.
- OpenBSD-Commit-ID: 381bddfcc1e297a42292222f3bcb5ac2b7ea2418
+ OpenBSD-Commit-ID: 1a8d9c67ae213ead180481900dbbb3e04864560d
-commit 349ecd4da3a985359694a74635748009be6baca6
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 18 23:13:42 2017 +0000
+commit 32e4e94e1511fe0020fbfbb62399d31b2d22a801
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon May 14 14:40:08 2018 +1000
- upstream commit
-
- pass kex->hostkey_alg and kex->hostkey_nid from pre-auth
- to post-auth unpriviledged child processes; ok markus@
+ sync fmt_scaled.c
- OpenBSD-Commit-ID: 4a35bc7af0a5f8a232d1361f79f4ebc376137302
+ revision 1.17
+ date: 2018/05/14 04:39:04; author: djm; state: Exp; lines: +5 -2;
+ commitid: 53zY8GjViUBnWo8Z;
+ constrain fractional part to [0-9] (less confusing to static analysis); ok ian@
-commit c9e37a8725c083441dd34a8a53768aa45c3c53fe
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Mon Dec 18 17:28:54 2017 +0000
+commit 54268d589e85ecc43d3eba8d83f327bdada9d696
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri May 11 14:04:40 2018 +1000
- upstream commit
+ fix key-options.sh on platforms without openpty(3)
- Add helper function for uri handing in scp where a
- missing path simply means ".". Also fix exit code and add warnings when an
- invalid uri is encountered. OK otto@
+ Skip the pty tests if the platform lacks openpty(3) and has to chown(2)
+ the pty device explicitly. This typically requires root permissions that
+ this test lacks.
- OpenBSD-Commit-ID: 47dcf872380586dabf7fcc6e7baf5f8ad508ae1a
+ bz#2856 ok dtucker@
-commit 04c7e28f83062dc42f2380d1bb3a6bf0190852c0
+commit b2140a739be4c3b43cc1dc08322dca39a1e39d20
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 18 02:25:15 2017 +0000
+Date: Fri May 11 03:38:51 2018 +0000
- upstream commit
+ upstream: implement EMFILE mitigation for ssh-agent: remember the
- pass negotiated signing algorithm though to
- sshkey_verify() and check that the negotiated algorithm matches the type in
- the signature (only matters for RSA SHA1/SHA2 sigs). ok markus@
+ fd rlimit and stop accepting new connections when it is exceeded (with some
+ grace). Accept is resumed when enough connections are closed.
- OpenBSD-Commit-ID: 735fb15bf4adc060d3bee9d047a4bcaaa81b1af9
+ bz#2576. feedback deraadt; ok dtucker@
+
+ OpenBSD-Commit-ID: 6a85d9cec7b85741961e7116a49f8dae777911ea
-commit 931c78dfd7fe30669681a59e536bbe66535f3ee9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 18 02:22:29 2017 +0000
+commit fdba503fdfc647ee8a244002f1581e869c1f3d90
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri May 11 03:22:55 2018 +0000
- upstream commit
+ upstream: Explicit cast when snprintf'ing an uint64. Prevents
- sshkey_sigtype() function to return the type of a
- signature; ok markus@
+ warnings on platforms where int64 is long not long long. ok djm@
- OpenBSD-Commit-ID: d3772b065ad6eed97285589bfb544befed9032e8
+ OpenBSD-Commit-ID: 9c5359e2fbfce11dea2d93f7bc257e84419bd001
-commit 4cdc5956f2fcc9e9078938db833142dc07d8f523
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Thu Dec 14 21:07:39 2017 +0000
+commit e7751aa4094d51a9bc00778aa8d07e22934c55ee
+Author: bluhm@openbsd.org <bluhm@openbsd.org>
+Date: Thu Apr 26 14:47:03 2018 +0000
- upstream commit
+ upstream: Since the previous commit, ssh regress test sftp-chroot was
- Replace ED25519's private SHA-512 implementation with a
- call to the regular digest code. This speeds up compilation considerably. ok
- markus@
+ failing. The sftp program terminated with the wrong exit code as sftp called
+ fatal() instad of exit(0). So when the sigchld handler waits for the child,
+ remember that it was found. Then don't expect that main() can wait again. OK
+ dtucker@
- OpenBSD-Commit-ID: fcce8c3bcfe7389462a28228f63c823e80ade41c
+ OpenBSD-Commit-ID: bfafd940c0de5297940c71ddf362053db0232266
-commit 012e5cb839faf76549e3b6101b192fe1a74d367e
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Tue Dec 12 15:06:12 2017 +0000
+commit 7c15301841e2e9d37cae732400de63ae9c0961d6
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Apr 29 17:54:12 2018 +1000
- upstream commit
-
- Create a persistent umac128.c source file: #define the
- output size and the name of the entry points for UMAC-128 before including
- umac.c. Idea from FreeBSD. ok dtucker@
+ Use includes.h instead of config.h.
- OpenBSD-Commit-ID: 463cfacfa07cb8060a4d4961e63dca307bf3f4b1
-
-commit b35addfb4cd3b5cdb56a2a489d38e940ada926c7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Dec 11 16:23:28 2017 +1100
-
- Update .depend with empty config.h
+ This ensures it picks up the definition of DEF_WEAK, the lack of which
+ can cause compile errors in some cases (eg modern AIX). From
+ michael at felt.demon.nl.
-commit 2d96f28246938e0ca474a939d8ac82ecd0de27e3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Dec 11 16:21:55 2017 +1100
+commit cec338967a666b7c8ad8b88175f2faeddf268116
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Apr 19 09:53:14 2018 +1000
- Ensure config.h is always in dependencies.
+ Omit 3des-cbc if OpenSSL built without DES.
- Put an empty config.h into the dependency list to ensure that it's
- always listed and consistent.
+ Patch from hongxu.jia at windriver.com, ok djm@
-commit ac4987a55ee5d4dcc8e87f7ae7c1f87be7257d71
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Sun Dec 10 19:37:57 2017 +0000
+commit a575ddd58835759393d2dddd16ebe5abdb56485e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Apr 16 22:50:44 2018 +0000
- upstream commit
+ upstream: Disable SSH2_MSG_DEBUG messages for Twisted Conch clients
- ssh/lib hasn't worked towards our code-sharing goals for
- a quit while, perhaps it is too verbose? Change each */Makefile to
- specifying exactly what sources that program requires, compiling it seperate.
- Maybe we'll iterate by sorting those into seperatable chunks, splitting up
- files which contain common code + server/client specific code, or whatnot.
- But this isn't one step, or we'd have done it a long time ago.. ok dtucker
- markus djm
+ without version numbers since they choke on them under some circumstances.
+ https://twistedmatrix.com/trac/ticket/9422 via Colin Watson
- OpenBSD-Commit-ID: 5317f294d63a876bfc861e19773b1575f96f027d
+ Newer Conch versions have a version number in their ident string and
+ handle debug messages okay. https://twistedmatrix.com/trac/ticket/9424
+
+ OpenBSD-Commit-ID: 6cf7be262af0419c58ddae11324d9c0dc1577539
-commit 48c23a39a8f1069a57264dd826f6c90aa12778d5
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Dec 10 05:55:29 2017 +0000
+commit 390c7000a8946db565b66eab9e52fb11948711fa
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Apr 14 21:50:41 2018 +0000
- upstream commit
+ upstream: don't free the %C expansion, it's used later for
- Put remote client info back into the ClientAlive
- connection termination message. Based in part on diff from lars.nooden at
- gmail, ok djm
+ LocalCommand
- OpenBSD-Commit-ID: 80a0f619a29bbf2f32eb5297a69978a0e05d0ee0
+ OpenBSD-Commit-ID: 857b5cb37b2d856bfdfce61289a415257a487fb1
-commit aabd75ec76575c1b17232e6526a644097cd798e5
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Fri Dec 8 03:45:52 2017 +0000
+commit 3455f1e7c48e2e549192998d330214975b9b1dc7
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Apr 13 05:04:12 2018 +0000
- upstream commit
+ upstream: notify user immediately when underlying ssh process dies;
- time_t printing needs %lld and (long long) casts ok djm
+ patch from Thomas Kuthan in bz2719; ok dtucker@
- OpenBSD-Commit-ID: 4a93bc2b0d42a39b8f8de8bb74d07ad2e5e83ef7
+ OpenBSD-Commit-ID: 78fac88c2f08054d1fc5162c43c24162b131cf78
-commit fd4eeeec16537870bd40d04836c7906ec141c17d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 8 02:14:33 2017 +0000
+commit 1c5b4bc827f4abc3e65888cda061ad5edf1b8c7c
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Apr 13 16:23:57 2018 +1000
- upstream commit
+ Allow nanosleep in preauth privsep child.
- fix ordering in previous to ensure errno isn't clobbered
- before logging.
+ The new timing attack mitigation code uses nanosleep in the preauth
+ codepath, allow in systrace andbox too.
+
+commit 0e73428038d5ecfa5d2a28cff26661502a7aff4e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Apr 13 16:06:29 2018 +1000
+
+ Allow nanosleep in preauth privsep child.
- OpenBSD-Commit-ID: e260bc1e145a9690dcb0d5aa9460c7b96a0c8ab2
+ The new timing attack mitigation code uses nanosleep in the preauth
+ codepath, allow in sandbox.
-commit 155072fdb0d938015df828836beb2f18a294ab8a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 8 02:13:02 2017 +0000
+commit e9d910b0289c820852f7afa67f584cef1c05fe95
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Apr 13 03:57:26 2018 +0000
- upstream commit
+ upstream: Defend against user enumeration timing attacks. This
- for some reason unix_listener() logged most errors twice
- with each message containing only some of the useful information; merge these
+ establishes a minimum time for each failed authentication attempt (5ms) and
+ adds a per-user constant derived from a host secret (0-4ms). Based on work
+ by joona.kannisto at tut.fi, ok markus@ djm@.
- OpenBSD-Commit-ID: 1978a7594a9470c0dddcd719586066311b7c9a4a
+ OpenBSD-Commit-ID: b7845b355bb7381703339c8fb0e57e81a20ae5ca
-commit 79c0e1d29959304e5a49af1dbc58b144628c09f3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Dec 11 14:38:33 2017 +1100
+commit d97874cbd909eb706886cd0cdd418f812c119ef9
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Apr 13 13:43:55 2018 +1000
- Add autogenerated dependency info to Makefile.
-
- Adds a .depend file containing dependency information generated by
- makedepend, which is appended to the generated Makefile by configure.
+ Using "==" in shell tests is not portable.
- You can regen the file with "make -f Makefile.in depend" if necessary,
- but we'll be looking at some way to automatically keep this up to date.
+ Patch from rsbecker at nexbridge.com.
+
+commit cfb1d9bc76734681e3dea532a1504fcd466fbe91
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Apr 13 13:38:06 2018 +1000
+
+ Fix tunnel forwarding broken in 7.7p1
- "no objection" djm@
+ bz2855, ok dtucker@
-commit f001de8fbf7f3faddddd8efd03df18e57601f7eb
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Dec 11 13:42:51 2017 +1100
+commit afa6e79b76fb52a0c09a29688b5c0d125eb08302
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Apr 13 13:31:42 2018 +1000
- Fix pasto in ldns handling.
+ prefer to use getrandom() for PRNG seeding
- When ldns-config is not found, configure would check the wrong variable.
- ok djm@
+ Only applies when built --without-openssl. Thanks Jann Horn for
+ reminder.
-commit c5bfe83f67cb64e71cf2fe0d1500f6904b0099ee
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Dec 9 10:12:23 2017 +1100
+commit 575fac34a97f69bc217b235f81de9f8f433eceed
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Apr 13 13:13:33 2018 +1000
- Portable switched to git so s/CVS/git/.
+ Revert $REGRESSTMP changes.
+
+ Revert 3fd2d229 and subsequent changes as they turned out to be a
+ portability hassle.
-commit bb82e61a40a4ee52e4eb904caaee2c27b763ab5b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sat Dec 9 08:06:00 2017 +1100
+commit 10479cc2a4acd6faaf643eb305233b49d70c31c1
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Apr 10 10:19:02 2018 +1000
- Remove now-used check for perl.
+ Many typo fixes from Karsten Weiss
+
+ Spotted using https://github.com/lucasdemarchi/codespell
-commit e0ce54c0b9ca3a9388f9c50f4fa6cc25c28a3240
+commit 907da2f88519b34189fd03fac96de0c52d448233
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Dec 6 05:06:21 2017 +0000
+Date: Tue Apr 10 00:14:10 2018 +0000
- upstream commit
-
- don't accept junk after "yes" or "no" responses to
- hostkey prompts. bz#2803 reported by Maksim Derbasov; ok dtucker@
+ upstream: more typos spotted by Karsten Weiss using codespell
- OpenBSD-Commit-ID: e1b159fb2253be973ce25eb7a7be26e6f967717c
+ OpenBSD-Regress-ID: d906a2aea0663810a658b7d0bc61a1d2907d4d69
-commit 609d96b3d58475a15b2eb6b3d463f2c5d8e510c0
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Dec 5 23:59:47 2017 +0000
+commit 37e5f4a7ab9a8026e5fc2f47dafb0f1b123d39e9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Apr 10 00:13:27 2018 +0000
- upstream commit
-
- Replace atoi and strtol conversions for integer arguments
- to config keywords with a checking wrapper around strtonum. This will
- prevent and flag invalid and negative arguments to these keywords. ok djm@
+ upstream: make this a bit more portable-friendly
- OpenBSD-Commit-ID: 99ae3981f3d608a219ccb8d2fff635ae52c17998
+ OpenBSD-Regress-ID: 62f7b9e055e8dfaab92b3825f158beeb4ca3f963
-commit 168ecec13f9d7cb80c07df3bf7d414f4e4165e84
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Dec 5 23:56:07 2017 +0000
+commit 001aa55484852370488786bd40e9fdad4b465811
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Apr 10 00:10:49 2018 +0000
- upstream commit
+ upstream: lots of typos in comments/docs. Patch from Karsten Weiss
- Add missing break for rdomain. Prevents spurious
- "Deprecated option" warnings. ok djm@
+ after checking with codespell tool
+ (https://github.com/lucasdemarchi/codespell)
- OpenBSD-Commit-ID: ba28a675d39bb04a974586241c3cba71a9c6099a
+ OpenBSD-Commit-ID: 373222f12d7ab606598a2d36840c60be93568528
-commit 927f8514ceffb1af380a5f63ab4d3f7709b1b198
+commit 260ede2787fe80b18b8d5920455b4fb268519c7d
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Dec 5 01:30:19 2017 +0000
+Date: Mon Apr 9 23:54:49 2018 +0000
- upstream commit
+ upstream: don't kill ssh-agent's listening socket entriely if we
- include the addr:port in bind/listen failure messages
+ fail to accept a connection; bz#2837, patch from Lukas Kuster
- OpenBSD-Commit-ID: fdadb69fe1b38692608809cf0376b71c2c28e58e
+ OpenBSD-Commit-ID: 52413f5069179bebf30d38f524afe1a2133c738f
-commit a8c89499543e2d889629c4e5e8dcf47a655cf889
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Nov 29 05:49:54 2017 +0000
+commit ebc8b4656f9b0f834a642a9fb3c9fbca86a61838
+Author: tj@openbsd.org <tj@openbsd.org>
+Date: Mon Apr 9 20:41:22 2018 +0000
- upstream commit
+ upstream: the UseLogin option was removed, so remove it here too.
- Import updated moduli.
+ ok dtucker
- OpenBSD-Commit-ID: 524d210f982af6007aa936ca7f4c977f4d32f38a
+ OpenBSD-Commit-ID: 7080be73a64d68e21f22f5408a67a0ba8b1b6b06
-commit 3dde09ab38c8e1cfc28252be473541a81bc57097
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Nov 28 21:10:22 2017 +0000
+commit 3e36f281851fc8e9c996b33f108b2ae167314fbe
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sun Apr 8 07:36:02 2018 +0000
- upstream commit
-
- Have sftp print a warning about shell cleanliness when
- decoding the first packet fails, which is usually caused by shells polluting
- stdout of non-interactive starups. bz#2800, ok markus@ deraadt@.
+ upstream: tweak previous;
- OpenBSD-Commit-ID: 88d6a9bf3470f9324b76ba1cbd53e50120f685b5
+ OpenBSD-Commit-ID: 2b9c23022ea7b9dddb62864de4e906000f9d7474
-commit 6c8a246437f612ada8541076be2414846d767319
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Dec 1 17:11:47 2017 +1100
+commit 8368571efd6693c5c57f850e23a2372acf3f865f
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Apr 7 13:50:10 2018 +0000
- Replace mkinstalldirs with mkdir -p.
+ upstream: tweak previous;
- Check for MIKDIR_P and use it instead of mkinstalldirs. Should fix "mkdir:
- cannot create directory:... File exists" during "make install".
- Patch from eb at emlix.com.
+ OpenBSD-Commit-ID: 38e347b6f8e888f5e0700d01abb1eba7caa154f9
-commit 3058dd78d2e43ed0f82ad8eab8bb04b043a72023
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Dec 1 17:07:08 2017 +1100
+commit 555294a7279914ae6795b71bedf4e6011b7636df
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Apr 6 13:02:39 2018 +0000
- Pull in newer install-sh from autoconf-2.69.
+ upstream: Allow "SendEnv -PATTERN" to clear environment variables
- Suggested by eb at emlix.com
-
-commit 79226e5413c5b0fda3511351a8511ff457e306d8
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Dec 1 16:55:35 2017 +1100
-
- Remove RSA1 host key generation.
+ previously labeled for sendind. bz#1285 ok dtucker@
- SSH1 support is now gone, remove SSH1 key generation.
- Patch from eb at emlix.com.
+ OpenBSD-Commit-ID: f6fec9e3d0f366f15903094fbe1754cb359a0df9
-commit 2937dd02c572a12f33d5c334d518f6cbe0b645eb
+commit 40f5f03544a07ebd2003b443d42e85cb51d94d59
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Nov 28 06:09:38 2017 +0000
+Date: Fri Apr 6 04:15:45 2018 +0000
- upstream commit
+ upstream: relax checking of authorized_keys environment="..."
- more whitespace errors
+ options to allow underscores in variable names (regression introduced in
+ 7.7). bz2851, ok deraadt@
- OpenBSD-Commit-ID: 5e11c125378327b648940b90145e0d98beb05abb
+ OpenBSD-Commit-ID: 69690ffe0c97ff393f2c76d25b4b3d2ed4e4ac9c
-commit 7f257bf3fd3a759f31098960cbbd1453fafc4164
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Tue Nov 28 06:04:51 2017 +0000
+commit 30fd7f9af0f553aaa2eeda5a1f53f26cfc222b5e
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Apr 6 03:51:27 2018 +0000
- upstream commit
+ upstream: add a couple of missed options to the config dump; patch
- whitespace at EOL
+ from Jakub Jelen via bz2835
- OpenBSD-Commit-ID: 76d3965202b22d59c2784a8df3a8bfa5ee67b96a
+ OpenBSD-Commit-ID: 5970adadf6ef206bee0dddfc75d24c2019861446
-commit 5db6fbf1438b108e5df3e79a1b4de544373bc2d4
-Author: dtucker@openbsd.org@openbsd.org <dtucker@openbsd.org@openbsd.org>
-Date: Sat Nov 25 06:46:22 2017 +0000
+commit 8d6829be324452d2acd282d5f8ceb0adaa89a4de
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Apr 6 03:34:27 2018 +0000
- upstream commit
+ upstream: ssh does not accept -oInclude=... on the commandline, the
- Add monotime_ts and monotime_tv that return monotonic
- timespec and timeval respectively. Replace calls to gettimeofday() in packet
- timing with monotime_tv so that the callers will work over a clock step.
- Should prevent integer overflow during clock steps reported by wangle6 at
- huawei.com. "I like" markus@
+ Include keyword is for configuration files only. bz#2840, patch from Jakub
+ Jelen
- OpenBSD-Commit-ID: 74d684264814ff806f197948b87aa732cb1b0b8a
+ OpenBSD-Commit-ID: 32d052b4a7a7f22df35fe3f71c368c02b02cacb0
-commit 2d638e986085bdf1a40310ed6e2307463db96ea0
-Author: dtucker@openbsd.org@openbsd.org <dtucker@openbsd.org@openbsd.org>
-Date: Sat Nov 25 05:58:47 2017 +0000
+commit 00c5222ddc0c8edcaa4ea45ac03befdc8013d137
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Apr 5 22:54:28 2018 +0000
- upstream commit
-
- Remove get_current_time() and replace with calls to
- monotime_double() which uses CLOCK_MONOTONIC and works over clock steps. "I
- like" markus@
+ upstream: We don't offer CBC cipher by default any more. Spotted by
- OpenBSD-Commit-ID: 3ad2f7d2414e2cfcaef99877a7a5b0baf2242952
-
-commit ba460acae48a36ef749cb23068f968f4d5d90a24
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 24 16:24:31 2017 +1100
-
- Include string.h for explicit_bzero.
-
-commit a65655fb1a12b77fb22f9e71559b9d73030ec8ff
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 24 10:23:47 2017 +1100
-
- fix incorrect range of OpenSSL versions supported
+ Renaud Allard (via otto@)
- Pointed out by Solar Designer
+ OpenBSD-Commit-ID: a559b1eef741557dd959ae378b665a2977d92dca
-commit 83a1e5dbec52d05775174f368e0c44b08619a308
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Wed Nov 15 02:10:16 2017 +0000
+commit 5ee8448ad7c306f05a9f56769f95336a8269f379
+Author: job@openbsd.org <job@openbsd.org>
+Date: Wed Apr 4 15:12:17 2018 +0000
- upstream commit
+ upstream: Update default IPQoS in ssh(1), sshd(8) to DSCP AF21 for
- downgrade a couple more request parsing errors from
- process-fatal to just returning failure, making them consistent with the
- others that were already like that.
+ interactive and CS1 for bulk
- OpenBSD-Commit-ID: c111461f7a626690a2d53018ef26557b34652918
-
-commit 93c68a8f3da8e5e6acdc3396f54d73919165e242
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Wed Nov 15 00:13:40 2017 +0000
-
- upstream commit
+ AF21 was selected as this is the highest priority within the low-latency
+ service class (and it is higher than what we have today). SSH is elastic
+ and time-sensitive data, where a user is waiting for a response via the
+ network in order to continue with a task at hand. As such, these flows
+ should be considered foreground traffic, with delays or drops to such
+ traffic directly impacting user-productivity.
- fix regression in 7.6: failure to parse a signature request
- message shouldn't be fatal to the process, just the request. Reported by Ron
- Frederick
+ For bulk SSH traffic, the CS1 "Lower Effort" marker was chosen to enable
+ networks implementing a scavanger/lower-than-best effort class to
+ discriminate scp(1) below normal activities, such as web surfing. In
+ general this type of bulk SSH traffic is a background activity.
- OpenBSD-Commit-ID: e5d01b3819caa1a2ad51fc57d6ded43f48bbcc05
-
-commit 548d3a66feb64c405733932a6b1abeaf7198fa71
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Tue Nov 14 00:45:29 2017 +0000
-
- upstream commit
+ An advantage of using "AF21" for interactive SSH and "CS1" for bulk SSH
+ is that they are recognisable values on all common platforms (IANA
+ https://www.iana.org/assignments/dscp-registry/dscp-registry.xml), and
+ for AF21 specifically a definition of the intended behavior exists
+ https://tools.ietf.org/html/rfc4594#section-4.7 in addition to the definition
+ of the Assured Forwarding PHB group https://tools.ietf.org/html/rfc2597, and
+ for CS1 (Lower Effort) there is https://tools.ietf.org/html/rfc3662
- fix problem in configuration parsing when in config dump mode
- (sshd -T) without providing a full connection specification (sshd -T -C ...)
+ The first three bits of "AF21" map to the equivalent IEEEE 802.1D PCP, IEEE
+ 802.11e, MPLS EXP/CoS and IP Precedence value of 2 (also known as "Immediate",
+ or "AC_BE"), and CS1's first 3 bits map to IEEEE 802.1D PCP, IEEE 802.11e,
+ MPLS/CoS and IP Precedence value 1 ("Background" or "AC_BK").
- spotted by bluhm@
+ OK deraadt@, "no objection" djm@
- OpenBSD-Commit-ID: 7125faf5740eaa9d3a2f25400a0bc85e94e28b8f
+ OpenBSD-Commit-ID: d11d2a4484f461524ef0c20870523dfcdeb52181
-commit 33edb6ebdc2f81ebed1bceadacdfb8910b64fb88
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Nov 3 05:18:44 2017 +0000
+commit 424b544fbda963f973da80f884717c3e0a513288
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Tue Apr 3 02:14:08 2018 +0000
- upstream commit
-
- reuse parse_multistate for parse_flag (yes/no arguments).
- Saves a few lines of code and makes the parser more consistent wrt case-
- sensitivity. bz#2664 ok dtucker@
+ upstream: Import regenerated moduli file.
- OpenBSD-Commit-ID: b2ad1b6086858d5db71c7b11e5a74dba6d60efef
+ OpenBSD-Commit-ID: 1de0e85522051eb2ffa00437e1885e9d7b3e0c2e
-commit d52131a98316e76c0caa348f09bf6f7b9b01a1b9
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Nov 3 05:14:04 2017 +0000
+commit 323f66ce934df2da551f256f37d69822428e1ca1
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Apr 6 04:18:35 2018 +0000
- upstream commit
+ upstream: Add test for username options parsing order, prompted by
- allow certificate validity intervals that specify only a
- start or stop time (we already support specifying both or neither)
+ bz#2849.
- OpenBSD-Commit-ID: 9be486545603c003030bdb5c467d1318b46b4e42
+ OpenBSD-Regress-ID: 6985cd32f38596882a3ac172ff8c510693b65283
-commit fbe8e7ac94c2fa380421a9205a8bc966549c2f91
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Nov 3 03:46:52 2017 +0000
+commit e8f474554e3bda102a797a2fbab0594ccc66f097
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Apr 6 14:11:44 2018 +1000
- upstream commit
-
- allow "cd" and "lcd" commands with no explicit path
- argument. lcd will change to the local user's home directory as usual. cd
- will change to the starting directory for session (because the protocol
- offers no way to obtain the remote user's home directory). bz#2760 ok
- dtucker@
+ Expose SSH_AUTH_INFO_0 to PAM auth modules
- OpenBSD-Commit-ID: 15333f5087cee8c1ed1330cac1bd0a3e6a767393
+ bz#2408, patch from Radoslaw Ejsmont; ok dtucker@
-commit 0208a48517b5e8e8b091f32fa4addcd67c31ca9e
-Author: dtucker@openbsd.org@openbsd.org <dtucker@openbsd.org@openbsd.org>
-Date: Fri Nov 3 03:18:53 2017 +0000
+commit 014ba209cf4c6a159baa30ecebbaddfa97da7100
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Apr 3 12:18:00 2018 +1000
- upstream commit
-
- When doing a config test with sshd -T, only require the
- attributes that are actually used in Match criteria rather than (an
- incomplete list of) all criteria. ok djm@, man page help jmc@
-
- OpenBSD-Commit-ID: b4e773c4212d3dea486d0259ae977551aab2c1fc
+ Import regenerated moduli file.
-commit c357eed5a52cd2f4ff358b17e30e3f9a800644da
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Nov 3 02:32:19 2017 +0000
+commit a0349a1cc4a18967ad1dbff5389bcdf9da098814
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Apr 2 15:38:28 2018 +1000
- upstream commit
-
- typos in ECDSA certificate names; bz#2787 reported by
- Mike Gerow
-
- OpenBSD-Commit-ID: 824938b6aba1b31321324ba1f56c05f84834b163
+ update versions in .spec files
-commit ecbf005b8fd80b81d0c61dfc1e96fe3da6099395
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Nov 3 02:29:17 2017 +0000
+commit 816ad38f79792f5617e3913be306ddb27e91091c
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Apr 2 15:38:20 2018 +1000
- upstream commit
-
- Private keys in PEM format have been encrypted by AES-128 for
- a while (not 3DES). bz#2788 reported by Calum Mackay
-
- OpenBSD-Commit-ID: bd33da7acbbb3c882f0a0ee56007a35ce0d8a11a
+ update version number
-commit 81c9ccdbf6ddbf9bfbd6f1f775a5a7c13e47e185
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 3 14:52:51 2017 +1100
+commit 2c71ca1dd1efe458cb7dee3f8a1a566f913182c2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Mar 30 18:23:07 2018 +1100
- Check for linux/if.h when enabling rdomain.
+ Disable native strndup and strnlen on AIX.
- musl libc doesn't seem to have linux/if.h, so check for its presence
- before enabling rdomain support on Linux.
+ On at least some revisions of AIX, strndup returns unterminated strings
+ under some conditions, apparently because strnlen returns incorrect
+ values in those cases. Disable both on AIX and use the replacements
+ from openbsd-compat. Fixes problem with ECDSA keys there, ok djm.
-commit fa1b834cce41a1ce3e6a8d57fb67ef18c9dd803f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Nov 3 14:09:45 2017 +1100
+commit 6b5a17bc14e896e3904dc58d889b58934cfacd24
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Mar 26 13:12:44 2018 +1100
- Add headers for sys/sysctl.h and net/route.h
+ Include ssh_api.h for struct ssh.
- On at least older OpenBSDs, sys/sysctl.h and net/route.h require
- sys/types and, in the case of sys/sysctl.h, sys/param.h for MAXLOGNAME.
+ struct ssh is needed by implementations of sys_auth_passwd() that were
+ converted in commit bba02a50. Needed to fix build on AIX, I assume for
+ the other platforms too (although it should be harmless if not needed).
-commit 41bff4da21fcd8a7c6a83a7e0f92b018f904f6fb
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Nov 3 02:22:41 2017 +0000
+commit bc3f80e4d191b8e48650045dfa8a682cd3aabd4d
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Mar 26 12:58:09 2018 +1100
- upstream commit
-
- avoid unused variable warnings for !WITH_OPENSSL; patch from
- Marcus Folkesson
+ Remove UNICOS code missed during removal.
- OpenBSD-Commit-ID: c01d27a3f907acdc3dd4ea48170fac3ba236d229
+ Fixes compile error on AIX.
-commit 6b373e4635a7470baa94253dd1dc8953663da9e8
-Author: Marcus Folkesson <marcus.folkesson@gmail.com>
-Date: Sat Oct 28 19:48:39 2017 +0200
+commit 9d57762c24882e2f000a21a0ffc8c5908a1fa738
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Sat Mar 24 19:29:03 2018 +0000
- only enable functions in dh.c when openssl is used
+ upstream: openssh-7.7
- Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
+ OpenBSD-Commit-ID: 274e614352460b9802c905f38fb5ea7ed5db3d41
-commit 939b30ba23848b572e15bf92f0f1a3d9cf3acc2b
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Wed Nov 1 00:04:15 2017 +0000
+commit 4b7d8acdbbceef247dc035e611e577174ed8a87e
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Mar 26 09:37:02 2018 +1100
- upstream commit
-
- fix broken stdout in ControlPersist mode, introduced by me in
- r1.467 and reported by Alf Schlichting
+ Remove authinfo.sh test dependency on printenv
- OpenBSD-Commit-ID: 3750a16e02108fc25f747e4ebcedb7123c1ef509
+ Some platforms lack printenv in the default $PATH.
+ Reported by Tom G. Christensen
-commit f21455a084f9cc3942cf1bde64055a4916849fed
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Oct 31 10:09:33 2017 +1100
+commit 4afeaf3dcb7dc70efd98fcfcb0ed28a6b40b820e
+Author: Tim Rice <tim@multitalents.net>
+Date: Sun Mar 25 10:00:21 2018 -0700
- Include includes.h for HAVE_GETPAGESIZE.
+ Use libiaf on all sysv5 systems
+
+commit bba02a5094b3db228ceac41cb4bfca165d0735f3
+Author: Tim Rice <tim@multitalents.net>
+Date: Sun Mar 25 09:17:33 2018 -0700
+
+ modified: auth-sia.c
+ modified: openbsd-compat/port-aix.c
+ modified: openbsd-compat/port-uw.c
- The configure script checks for getpagesize() and sets HAVE_GETPAGESIZE in
- config.h, but bsd-getpagesize.c forgot to include includes.h (which
- indirectly includes config.h) so the checks always fails, causing linker
- issues when linking statically on systems with getpagesize().
+ propogate changes to auth-passwd.c in commit
+ 7c856857607112a3dfe6414696bf4c7ab7fb0cb3 to other providers
+ of sys_auth_passwd()
+
+commit d7a7a39168bdfe273587bf85d779d60569100a3f
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Sat Mar 24 19:29:03 2018 +0000
+
+ upstream: openssh-7.7
- Patch from Peter Korsgaard <peter at korsgaard.com>
+ OpenBSD-Commit-ID: 274e614352460b9802c905f38fb5ea7ed5db3d41
-commit f2ad63c0718b93ac1d1e85f53fee33b06eef86b5
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Mon Oct 30 22:01:52 2017 +0000
+commit 9efcaaac314c611c6c0326e8bac5b486c424bbd2
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Sat Mar 24 19:28:43 2018 +0000
- upstream commit
+ upstream: fix bogus warning when signing cert keys using agent;
- whitespace at EOL
+ from djm; ok deraadt dtucker
- OpenBSD-Regress-ID: f4b5df99b28c6f63478deb916c6ed0e794685f07
+ OpenBSD-Commit-ID: 12e50836ba2040042383a8b71e12d7ea06e9633d
-commit c6415b1f8f1d0c2735564371647fd6a177fb9a3e
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Mon Oct 30 21:59:43 2017 +0000
+commit 393436024d2e4b4c7a01f9cfa5854e7437896d11
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Mar 25 09:40:46 2018 +1100
- upstream commit
-
- whitespace at EOL
+ Replace /dev/stdin with "-".
- OpenBSD-Regress-ID: 19b1394393deee4c8a2114a3b7d18189f27a15cd
+ For some reason sftp -b doesn't work with /dev/stdin on Cygwin, as noted
+ and suggested by vinschen at redhat.com.
-commit e4d4ddbbba0e585ca3ec3a455430750b4622a6d3
-Author: millert@openbsd.org@openbsd.org <millert@openbsd.org@openbsd.org>
-Date: Wed Oct 25 20:08:36 2017 +0000
+commit b5974de1a1d419e316ffb6524b1b277dda2f3b49
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Mar 23 13:21:14 2018 +1100
- upstream commit
+ Provide $OBJ to paths in PuTTY interop tests.
+
+commit dc31e79454e9b9140b33ad380565fdb59b9c4f33
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Mar 16 09:06:31 2018 +0000
+
+ upstream: Tell puttygen to use /dev/urandom instead of /dev/random. On
- Use printenv to test whether an SSH_USER_AUTH is set
- instead of using $SSH_USER_AUTH. The latter won't work with csh which treats
- unknown variables as an error when expanding them. OK markus@
+ OpenBSD they are both non-blocking, but on many other -portable platforms it
+ blocks, stalling tests.
- OpenBSD-Regress-ID: f601e878dd8b71aa40381573dde3a8f567e6f2d1
+ OpenBSD-Regress-ID: 397d0d4c719c353f24d79f5b14775e0cfdf0e1cc
-commit 116b1b439413a724ebb3320633a64dd0f3ee1fe7
-Author: millert@openbsd.org@openbsd.org <millert@openbsd.org@openbsd.org>
-Date: Tue Oct 24 19:33:32 2017 +0000
+commit cb1f94431ef319cd48618b8b771b58739a8210cf
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Thu Mar 22 07:06:11 2018 +0000
- upstream commit
-
- Add tests for URI parsing. OK markus@
+ upstream: ssh/xmss: fix build; ok djm@
- OpenBSD-Regress-ID: 5d1df19874f3b916d1a2256a905526e17a98bd3b
+ OpenBSD-Commit-ID: c9374ca41d4497f1c673ab681cc33f6e7c5dd186
-commit dbe0662e9cd482593a4a8bf58c6481bfe8a747a4
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Oct 27 01:57:06 2017 +0000
+commit 27979da9e4074322611355598f69175b9ff10d39
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Thu Mar 22 07:05:48 2018 +0000
- upstream commit
+ upstream: ssh/xmss: fix deserialize for certs; ok djm@
- whitespace at EOL
+ OpenBSD-Commit-ID: f44c41636c16ec83502039828beaf521c057dddc
+
+commit c6cb2565c9285eb54fa9dfbb3890f5464aff410f
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Mar 22 17:00:28 2018 +1100
+
+ Save $? before case statement.
- OpenBSD-Commit-ID: c95549cf5a07d56ea11aaff818415118720214f6
+ In some shells (FreeBSD 9, ash) the case statement resets $?, so save
+ for later testing.
-commit d2135474344335a7c6ee643b6ade6db400fa76ee
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Oct 27 01:01:17 2017 +0000
+commit 4c4e7f783b43b264c247233acb887ee10ed4ce4d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Mar 14 05:35:40 2018 +0000
- upstream commit
+ upstream: rename recently-added "valid-before" key restriction to
- whitespace at EOL (lots)
+ "expiry-time" as the former is confusing wrt similar terminology in X.509;
+ pointed out by jsing@
- OpenBSD-Commit-ID: 757257dd44116794ee1b5a45c6724973de181747
+ OpenBSD-Regress-ID: ac8b41dbfd90cffd525d58350c327195b0937793
-commit b77c29a07f5a02c7c1998701c73d92bde7ae1608
-Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
-Date: Fri Oct 27 00:18:41 2017 +0000
+commit 500396b204c58e78ad9d081516a365a9f28dc3fd
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Mar 12 00:56:03 2018 +0000
- upstream commit
+ upstream: check valid-before option in authorized_keys
- improve printing of rdomain on accept() a little
+ OpenBSD-Regress-ID: 7e1e4a84f7f099a290e5a4cbf4196f90ff2d7e11
+
+commit a76b5d26c2a51d7dd7a5164e683ab3f4419be215
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Mar 12 00:54:04 2018 +0000
+
+ upstream: explicitly specify RSA/SHA-2 keytype here too
- OpenBSD-Commit-ID: 5da58db2243606899cedaa646c70201b2d12247a
+ OpenBSD-Regress-ID: 74d7b24e8c72c27af6b481198344eb077e993a62
-commit 68d3bbb2e6dfbf117c46e942142795b2cdd0274b
-Author: jmc@openbsd.org@openbsd.org <jmc@openbsd.org@openbsd.org>
-Date: Thu Oct 26 06:44:01 2017 +0000
+commit 3a43297ce29d37c64e37c7e21282cb219e28d3d1
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Mar 12 00:52:57 2018 +0000
- upstream commit
+ upstream: exlicitly include RSA/SHA-2 keytypes in
- mark up the rdomain keyword;
+ PubkeyAcceptedKeyTypes here
- OpenBSD-Commit-ID: 1b597d0ad0ad20e94dbd61ca066057e6f6313b8a
+ OpenBSD-Regress-ID: 954d19e0032a74e31697fb1dc7e7d3d1b2d65fe9
-commit 0b2e2896b9d0d6cfb59e9ec8271085296bd4e99b
-Author: jmc@openbsd.org@openbsd.org <jmc@openbsd.org@openbsd.org>
-Date: Wed Oct 25 06:19:46 2017 +0000
+commit 037fdc1dc2d68e1d43f9c9e2586c02cabc8f7cc8
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Wed Mar 14 06:56:20 2018 +0000
- upstream commit
+ upstream: sort expiry-time;
- tweak the uri text, specifically removing some markup to
- make it a bit more readable;
+ OpenBSD-Commit-ID: 8c7d82ee1e63e26ceb2b3d3a16514019f984f6bf
+
+commit abc0fa38c9bc136871f28e452c3465c3051fc785
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Mar 14 05:35:40 2018 +0000
+
+ upstream: rename recently-added "valid-before" key restriction to
- issue reported by - and diff ok - millert
+ "expiry-time" as the former is confusing wrt similar terminology in X.509;
+ pointed out by jsing@
- OpenBSD-Commit-ID: 8b56a20208040b2d0633536fd926e992de37ef3f
+ OpenBSD-Commit-ID: 376939466a1f562f3950a22314bc6505733aaae6
-commit 7530e77bdc9415386d2a8ea3d086e8b611b2ba40
-Author: jmc@openbsd.org@openbsd.org <jmc@openbsd.org@openbsd.org>
-Date: Wed Oct 25 06:18:06 2017 +0000
+commit bf0fbf2b11a44f06a64b620af7d01ff171c28e13
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Mar 12 00:52:01 2018 +0000
- upstream commit
+ upstream: add valid-before="[time]" authorized_keys option. A
- simplify macros in previous, and some minor tweaks;
+ simple way of giving a key an expiry date. ok markus@
- OpenBSD-Commit-ID: 6efeca3d8b095b76e21b484607d9cc67ac9a11ca
+ OpenBSD-Commit-ID: 1793b4dd5184fa87f42ed33c7b0f4f02bc877947
-commit eb9c582b710dc48976b48eb2204218f6863bae9a
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Oct 31 00:46:29 2017 +1100
+commit fbd733ab7adc907118a6cf56c08ed90c7000043f
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Mar 12 19:17:26 2018 +1100
- Switch upstream git repository.
+ Add AC_LANG_PROGRAM to AC_COMPILE_IFELSE.
- Previously portable OpenSSH has synced against a conversion of OpenBSD's
- CVS repository made using the git cvsimport tool, but this has become
- increasingly unreliable.
+ The recently added MIPS ABI tests need AC_LANG_PROGRAM to prevent
+ warnings from autoconf. Pointed out by klausz at haus-gisela.de.
+
+commit c7c458e8261b04d161763cd333d74e7a5842e917
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Mar 7 23:53:08 2018 +0000
+
+ upstream: revert recent strdelim() change, it causes problems with
- As of this commit, portable OpenSSH now tracks a conversion of the
- OpenBSD CVS upstream made using the excellent cvs2gitdump tool from
- YASUOKA Masahiko: https://github.com/yasuoka/cvs2gitdump
+ some configs.
- cvs2gitdump is considerably more reliable than gitcvsimport and the old
- version of cvsps that it uses under the hood, and is the same tool used
- to export the entire OpenBSD repository to git (so we know it can cope
- with future growth).
+ revision 1.124
+ date: 2018/03/02 03:02:11; author: djm; state: Exp; lines: +19 -8; commitid: nNRsCijZiGG6SUTT;
+ Allow escaped quotes \" and \' in ssh_config and sshd_config quotes
+ option strings. bz#1596 ok markus@
- These new conversions are mirrored at github, so interested parties can
- match portable OpenSSH commits to their upstream counterparts.
+ OpenBSD-Commit-ID: 59c40b1b81206d713c06b49d8477402c86babda5
+
+commit 0bcd871ccdf3baf2b642509ba4773d5be067cfa2
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Mon Mar 5 07:03:18 2018 +0000
+
+ upstream: move the input format details to -f; remove the output
- https://github.com/djmdjm/openbsd-openssh-src
- https://github.com/djmdjm/openbsd-openssh-regress
+ format details and point to sshd(8), where it is documented;
- An unfortunate side effect of switching upstreams is that we must have
- a flag day, across which the upstream commit IDs will be inconsistent.
- The old commit IDs are recorded with the tags "Upstream-ID" for main
- directory commits and "Upstream-Regress-ID" for regress commits.
+ ok dtucker
- To make it clear that the commit IDs do not refer to the same
- things, the new repository will instead use "OpenBSD-ID" and
- "OpenBSD-Regress-ID" tags instead.
+ OpenBSD-Commit-ID: 95f17e47dae02a6ac7329708c8c893d4cad0004a
+
+commit 45011511a09e03493568506ce32f4891a174a3bd
+Author: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
+Date: Tue Jun 20 16:42:28 2017 +0100
+
+ configure.ac: properly set seccomp_audit_arch for MIPS64
- Apart from being a longwinded explanation of what is going on, this
- commit message also serves to synchronise our tools with the state of
- the tree, which happens to be:
+ Currently seccomp_audit_arch is set to AUDIT_ARCH_MIPS64 or
+ AUDIT_ARCH_MIPSEL64 (depending on the endinness) when openssh is built
+ for MIPS64. However, that's only valid for n64 ABI. The right macros for
+ n32 ABI defined in seccomp.h are AUDIT_ARCH_MIPS64N32 and
+ AUDIT_ARCH_MIPSEL64N32, for big and little endian respectively.
- OpenBSD-ID: 9c43a9968c7929613284ea18e9fb92e4e2a8e4c1
- OpenBSD-Regress-ID: b33b385719420bf3bc57d664feda6f699c147fef
+ Because of that an sshd built for MIPS64 n32 rejects connection attempts
+ and the output of strace reveals that the problem is related to seccomp
+ audit:
+
+ [pid 194] prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=57,
+ filter=0x555d5da0}) = 0
+ [pid 194] write(7, "\0\0\0]\0\0\0\5\0\0\0Ulist_hostkey_types: "..., 97) = ?
+ [pid 193] <... poll resumed> ) = 2 ([{fd=5, revents=POLLIN|POLLHUP},
+ {fd=6, revents=POLLHUP}])
+ [pid 194] +++ killed by SIGSYS +++
+
+ This patch fixes that problem by setting the right value to
+ seccomp_audit_arch taking into account the MIPS64 ABI.
+
+ Signed-off-by: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
-commit 2de5c6b53bf063ac698596ef4e23d8e3099656ea
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 27 08:42:33 2017 +1100
+commit 580086704c31de91dc7ba040a28e416bf1fefbca
+Author: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
+Date: Tue Jun 20 16:42:11 2017 +0100
- fix rdomain compilation errors
+ configure.ac: detect MIPS ABI
+
+ Signed-off-by: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
-commit 6bd5b569fd6dfd5e8c8af20bbc41e45c2d6462ab
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 14:15:42 2017 +1100
+commit cd4e937aa701f70366cd5b5969af525dff6fdf15
+Author: Alan Yee <alyee@ucsd.edu>
+Date: Wed Mar 7 15:12:14 2018 -0800
- autoconf glue to enable Linux VRF
+ Use https URLs for links that support it.
-commit 97c5aaf925d61641d599071abb56012cde265978
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 14:09:56 2017 +1100
+commit c0a0c3fc4a76b682db22146b28ddc46566db1ce9
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Mar 5 20:03:07 2018 +1100
- basic valid_rdomain() implementation for Linux
+ Disable UTMPX on SunOS4.
-commit ce1cca39d7935dd394080ce2df62f5ce5b51f485
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 13:47:59 2017 +1100
+commit 58fd4c5c0140f6636227ca7acbb149ab0c2509b9
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Mar 5 19:28:08 2018 +1100
- implement get/set_rdomain() for Linux
+ Check for and work around buggy fflush(NULL).
- Not enabled, pending implementation of valid_rdomain() and autoconf glue
+ Some really old platforms (eg SunOS4) segfault on fflush(NULL) so check
+ for and work around. With klausz at haus-gisela.de.
-commit 6eee79f9b8d4a3b113b698383948a119acb82415
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 13:22:29 2017 +1100
+commit 71e48bc7945f867029e50e06c665c66aed6d3c64
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Mar 5 10:22:32 2018 +1100
- stubs for rdomain replacement functions
+ Remove extra XMSS #endif
+
+ Extra #endif breaks compile with -DWITH_XMSS. Pointed out by Jack
+ Schmidt via github.
-commit f5594f939f844bbb688313697d6676238da355b3
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 13:13:57 2017 +1100
+commit 055e09e2212ff52067786bf6d794ca9512ff7f0c
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sat Mar 3 06:37:53 2018 +0000
- rename port-tun.[ch] => port-net.[ch]
+ upstream: Update RSA minimum modulus size to 1024. sshkey.h rev 1.18
- Ahead of adding rdomain support
+ bumped the minimum from 768 to 1024, update man page accordingly.
+
+ OpenBSD-Commit-ID: 27563ab4e866cd2aac40a5247876f6787c08a338
-commit d685e5a31feea35fb99e1a31a70b3c60a7f2a0eb
+commit 7e4fadd3248d6bb7d39d6688c76a613d35d2efc1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 25 02:10:39 2017 +0000
+Date: Sun Mar 4 01:46:48 2018 +0000
- upstream commit
+ upstream: for the pty control tests, just check that the PTY path
- uninitialised variable in PermitTunnel printing code
+ points to something in /dev (rather than checking the device node itself);
+ makes life easier for portable, where systems with dynamic ptys can delete
+ nodes before we get around to testing their existence.
- Upstream-ID: f04dc33e42855704e116b8da61095ecc71bc9e9a
+ OpenBSD-Regress-ID: b1e455b821e62572bccd98102f8dd9d09bb94994
-commit 43c29bb7cfd46bbbc61e0ffa61a11e74d49a712f
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 13:10:59 2017 +1100
+commit 13ef4cf53f24753fe920832b990b25c9c9cd0530
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Mar 3 16:21:20 2018 +1100
- provide hooks and fallbacks for rdomain support
+ Update PAM password change to new opts API.
-commit 3235473bc8e075fad7216b7cd62fcd2b0320ea04
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Oct 25 11:25:43 2017 +1100
+commit 33561e68e0b27366cb769295a077aabc6a49d2a1
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Mar 3 14:56:09 2018 +1100
- check for net/route.h and sys/sysctl.h
+ Add strndup for platforms that need it.
+
+ Some platforms don't have strndup, which includes Solaris 10, NetBSD 3
+ and FreeBSD 6.
-commit 4d5456c7de108e17603a0920c4d15bca87244921
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 25 00:21:37 2017 +0000
+commit e8a17feba95eef424303fb94441008f6c5347aaf
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Mar 3 14:49:07 2018 +1100
- upstream commit
+ Flatten and alphabetize object file lists.
- transfer ownership of stdout to the session channel by
- dup2'ing /dev/null to fd 1. This allows propagation of remote stdout close to
- the local side; reported by David Newall, ok markus@
+ This will make maintenance and changes easier. "no objection" tim@
+
+commit de1920d743d295f50e6905e5957c4172c038e8eb
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Mar 3 03:16:17 2018 +0000
+
+ upstream: unit tests for new authorized_keys options API
- Upstream-ID: 8d9ac18a11d89e6b0415f0cbf67b928ac67f0e79
+ OpenBSD-Regress-ID: 820f9ec9c6301f6ca330ad4052d85f0e67d0bdc1
-commit 68af80e6fdeaeb79432209db614386ff0f37e75f
+commit dc3e92df17556dc5b0ab19cee8dcb2a6ba348717
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 25 00:19:47 2017 +0000
+Date: Fri Mar 2 02:53:27 2018 +0000
- upstream commit
+ upstream: fix testing of pty option, include positive test and
- add a "rdomain" criteria for the sshd_config Match
- keyword to allow conditional configuration that depends on which rdomain(4) a
- connection was recevied on. ok markus@
+ testing of restrict keyword
- Upstream-ID: 27d8fd5a3f1bae18c9c6e533afdf99bff887a4fb
+ OpenBSD-Regress-ID: 4268f27c2706a0a95e725d9518c5bcbec9814c6d
-commit 35eb33fb957979e3fcbe6ea0eaee8bf4a217421a
+commit 3d1edd1ebbc0aabea8bbe61903060f37137f7c61
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 25 00:17:08 2017 +0000
+Date: Fri Mar 2 02:51:55 2018 +0000
- upstream commit
-
- add sshd_config RDomain keyword to place sshd and the
- subsequent user session (including the shell and any TCP/IP forwardings) into
- the specified rdomain(4)
+ upstream: better testing for port-forwarding and restrict flags in
- ok markus@
+ authorized_keys
- Upstream-ID: be2358e86346b5cacf20d90f59f980b87d1af0f5
+ OpenBSD-Regress-ID: ee771df8955f2735df54746872c6228aff381daa
-commit acf559e1cffbd1d6167cc1742729fc381069f06b
+commit 7c856857607112a3dfe6414696bf4c7ab7fb0cb3
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 25 00:15:35 2017 +0000
+Date: Sat Mar 3 03:15:51 2018 +0000
- upstream commit
+ upstream: switch over to the new authorized_keys options API and
- Add optional rdomain qualifier to sshd_config's
- ListenAddress option to allow listening on a different rdomain(4), e.g.
+ remove the legacy one.
- ListenAddress 0.0.0.0 rdomain 4
+ Includes a fairly big refactor of auth2-pubkey.c to retain less state
+ between key file lines.
- Upstream-ID: 24b6622c376feeed9e9be8b9605e593695ac9091
+ feedback and ok markus@
+
+ OpenBSD-Commit-ID: dece6cae0f47751b9892080eb13d6625599573df
-commit b9903ee8ee8671b447fc260c2bee3761e26c7227
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Tue Oct 24 19:41:45 2017 +0000
+commit 90c4bec8b5f9ec4c003ae4abdf13fc7766f00c8b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Mar 3 03:06:02 2018 +0000
- upstream commit
+ upstream: Introduce a new API for handling authorized_keys options.
- Kill dead store and some spaces vs. tabs indent in
- parse_user_host_path(). Noticed by markus@
+ This API parses options to a dedicated structure rather than the old API's
+ approach of setting global state. It also includes support for merging
+ options, e.g. from authorized_keys, authorized_principals and/or
+ certificates.
- Upstream-ID: 114fec91dadf9af46c7c94fd40fc630ea2de8200
+ feedback and ok markus@
+
+ OpenBSD-Commit-ID: 98badda102cd575210d7802943e93a34232c80a2
-commit 0869627e00f4ee2a038cb62d7bd9ffad405e1800
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue Oct 24 06:27:42 2017 +0000
+commit 26074380767e639ef89321610e146ae11016b385
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Mar 3 03:01:50 2018 +0000
- upstream commit
+ upstream: warn when the agent returns a signature type that was
- tweak previous; ok djm
+ different to what was requested. This might happen when an old/non-OpenSSH
+ agent is asked to make a rsa-sha2-256/512 signature but only supports
+ ssh-rsa. bz#2799 feedback and ok markus@
- Upstream-ID: 7d913981ab315296be1f759c67b6e17aea38fca9
+ OpenBSD-Commit-ID: 760c0f9438c5c58abc16b5f98008ff2d95cb13ce
-commit e3fa20e2e58fdc88a0e842358778f2de448b771b
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Oct 23 16:25:24 2017 +1100
+commit f493d2b0b66fb003ed29f31dd66ff1aeb64be1fc
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Mar 2 21:40:15 2018 +0000
- avoid -Wsign-compare warning in argv copying
+ upstream: apply a lick of paint; tweaks/ok dtucker
+
+ OpenBSD-Commit-ID: 518a6736338045e0037f503c21027d958d05e703
-commit b7548b12a6b2b4abf4d057192c353147e0abba08
+commit 713d9cb510e0e7759398716cbe6dcf43e574be71
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Oct 23 05:08:00 2017 +0000
+Date: Fri Mar 2 03:02:11 2018 +0000
- upstream commit
-
- Expose devices allocated for tun/tap forwarding.
-
- At the client, the device may be obtained from a new %T expansion
- for LocalCommand.
-
- At the server, the allocated devices will be listed in a
- SSH_TUNNEL variable exposed to the environment of any user sessions
- started after the tunnel forwarding was established.
-
- ok markus
-
- Upstream-ID: e61e53f8ae80566e9ddc0d67a5df5bdf2f3c9f9e
-
-commit 887669ef032d63cf07f53cada216fa8a0c9a7d72
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Sat Oct 21 23:06:24 2017 +0000
-
- upstream commit
+ upstream: Allow escaped quotes \" and \' in ssh_config and
- Add URI support to ssh, sftp and scp. For example
- ssh://user@host or sftp://user@host/path. The connection parameters
- described in draft-ietf-secsh-scp-sftp-ssh-uri-04 are not implemented since
- the ssh fingerprint format in the draft uses md5 with no way to specify the
- hash function type. OK djm@
+ sshd_config quotes option strings. bz#1596 ok markus@
- Upstream-ID: 4ba3768b662d6722de59e6ecb00abf2d4bf9cacc
-
-commit d27bff293cfeb2252f4c7a58babe5ad3262c6c98
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 20 13:22:00 2017 +1100
-
- Fix missed RCSID merges
+ OpenBSD-Commit-ID: dd3a29fc2dc905e8780198e5a6a30b096de1a1cb
-commit d3b6aeb546242c9e61721225ac4387d416dd3d5e
+commit 94b4e2d29afaaaef89a95289b16c18bf5627f7cd
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Oct 20 02:13:41 2017 +0000
+Date: Fri Mar 2 02:08:03 2018 +0000
- upstream commit
+ upstream: refactor sshkey_read() to make it a little more, err,
- more RCSIDs
+ readable. ok markus
- Upstream-Regress-ID: 1aecbe3f8224793f0ec56741a86d619830eb33be
+ OpenBSD-Commit-ID: 2e9247b5762fdac3b6335dc606d3822121714c28
-commit b011edbb32e41aaab01386ce4c0efcc9ff681c4a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Oct 20 01:56:39 2017 +0000
+commit 5886b92968b360623491699247caddfb77a74d80
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Thu Mar 1 20:32:16 2018 +0000
- upstream commit
+ upstream: missing #ifdef for _PATH_HOST_XMSS_KEY_FILE; report by
- add RCSIDs to these; they make syncing portable a bit
- easier
+ jmc@
- Upstream-ID: 56cb7021faea599736dd7e7f09c2e714425b1e68
+ OpenBSD-Commit-ID: 9039cb69a3f9886bfef096891a9e7fcbd620280b
-commit 6eb27597781dccaf0ec2b80107a9f0592a0cb464
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 20 12:54:15 2017 +1100
+commit 3b36bed3d26f17f6a2b7e036e01777770fe1bcd4
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Feb 26 12:14:53 2018 +0000
- upstream commit
-
- Apply missing commit 1.11 to kexc25519s.c
+ upstream: Remove unneeded (local) include. ok markus@
- Upstream-ID: 5f020e23a1ee6c3597af1f91511e68552cdf15e8
+ OpenBSD-Commit-ID: 132812dd2296b1caa8cb07d2408afc28e4e60f93
-commit 6f72280553cb6918859ebcacc717f2d2fafc1a27
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 20 12:52:50 2017 +1100
+commit 27b9f3950e0289e225b57b7b880a8f1859dcd70b
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Feb 26 03:56:44 2018 +0000
- upstream commit
+ upstream: Add $OpenBSD$ markers to xmss files to help keep synced
- Apply missing commit 1.127 to servconf.h
+ with portable. ok djm@.
- Upstream-ID: f14c4bac74a2b7cf1e3cff6bea5c447f192a7d15
+ OpenBSD-Commit-ID: 5233a27aafd1dfadad4b957225f95ae51eb365c1
-commit bb3e16ab25cb911238c2eb7455f9cf490cb143cc
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Wed Oct 18 05:36:59 2017 +0000
+commit afd830847a82ebbd5aeab05bad6d2c8ce74df1cd
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Feb 26 03:03:05 2018 +0000
- upstream commit
-
- remove unused Pp;
+ upstream: Add newline at end of file to prevent compiler warnings.
- Upstream-ID: 8ad26467f1f6a40be887234085a8e01a61a00550
+ OpenBSD-Commit-ID: 52f247d4eafe840c7c14c8befa71a760a8eeb063
-commit 05b69e99570553c8e1eafb895b1fbf1d098d2e14
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 18 02:49:44 2017 +0000
+commit 941e0d3e9bb8d5e4eb70cc694441445faf037c84
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Wed Feb 28 19:59:35 2018 +1100
- upstream commit
-
- In the description of pattern-lists, clarify negated
- matches by explicitly stating that a negated match will never yield a
- positive result, and that at least one positive term in the pattern-list must
- match. bz#1918
+ Add WITH_XMSS, move to prevent conflicts.
- Upstream-ID: 652d2f9d993f158fc5f83cef4a95cd9d95ae6a14
+ Add #ifdef WITH_XMSS to ssh-xmss.c, move it in the other files to after
+ includes.h so it's less likely to conflict and will pick up WITH_XMSS if
+ added to config.h.
-commit eb80e26a15c10bc65fed8b8cdb476819a713c0fd
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Oct 13 21:13:54 2017 +0000
+commit a10d8552d0d2438da4ed539275abcbf557d1e7a8
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 27 14:45:17 2018 +1100
- upstream commit
-
- log debug messages sent to peer; ok deraadt markus
+ Conditionally compile XMSS code.
- Upstream-ID: 3b4fdc0a06ea5083f61d96e20043000f477103d9
+ The XMSS code is currently experimental and, unlike the rest of OpenSSH
+ cannot currently be compiled with a c89 compiler.
-commit 071325f458d615d7740da5c1c1d5a8b68a0b4605
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Oct 13 16:50:45 2017 +0000
+commit 146c3bd28c8dbee9c4b06465d9c9facab96b1e9b
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 12:51:29 2018 +1100
- upstream commit
-
- trim permitrootlogin description somewhat, to avoid
- ambiguity; original diff from walter alejandro iglesias, tweaked by sthen and
- myself
-
- ok sthen schwarze deraadt
-
- Upstream-ID: 1749418b2bc073f3fdd25fe21f8263c3637fe5d2
+ Check dlopen has RTLD_NOW before enabling pkcs11.
-commit 10727487becb897a15f658e0cb2d05466236e622
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Oct 13 06:45:18 2017 +0000
+commit 1323f120d06a26074c4d154fcbe7f49bcad3d741
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 27 08:41:25 2018 +1100
- upstream commit
-
- mention SSH_USER_AUTH in the list of environment
- variables
+ Check for attributes on prototype args.
- Upstream-ID: 1083397c3ee54b4933121ab058c70a0fc6383691
+ Some compilers (gcc 2.9.53, 3.0 and probably others, see gcc bug #3481)
+ do not accept __attribute__ on function pointer prototype args. Check for
+ this and hide them if they're not accepted.
-commit 224f193d6a4b57e7a0cb2b9ecd3b6c54d721d8c2
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Oct 13 06:24:51 2017 +0000
+commit f0b245b0439e600fab782d19e97980e9f2c2533c
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 11:43:48 2018 +1100
- upstream commit
-
- BIO_get_mem_data() is supposed to take a char* as pointer
- argument, so don't pass it a const char*
-
- Upstream-ID: 1ccd91eb7f4dd4f0fa812d4f956987cd00b5f6ec
+ Check if HAVE_DECL_BZERO correctly.
-commit cfa46825b5ef7097373ed8e31b01a4538a8db565
-Author: benno@openbsd.org <benno@openbsd.org>
-Date: Mon Oct 9 20:12:51 2017 +0000
+commit c7ef4a399155e1621a532cc5e08e6fa773658dd4
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 17:42:56 2018 +1100
- upstream commit
-
- clarify the order in which config statements are used. ok
- jmc@ djm@
-
- Upstream-ID: e37e27bb6bbac71315e22cb9690fd8a556a501ed
+ Wrap <stdint.h> in #ifdef HAVE_STDINT_H.
-commit dceabc7ad7ebc7769c8214a1647af64c9a1d92e5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Oct 5 15:52:03 2017 +0000
+commit ac53ce46cf8165cbda7f57ee045f9f32e1e92b31
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 16:24:23 2018 +1100
- upstream commit
-
- replace statically-sized arrays in ServerOptions with
- dynamic ones managed by xrecallocarray, removing some arbitrary (though
- large) limits and saving a bit of memory; "much nicer" markus@
+ Replace $(CURDIR) with $(PWD).
- Upstream-ID: 1732720b2f478fe929d6687ac7b0a97ff2efe9d2
+ The former doesn't work on Solaris or BSDs.
-commit 2b4f3ab050c2aaf6977604dd037041372615178d
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Thu Oct 5 12:56:50 2017 +0000
+commit 534b2680a15d14e7e60274d5b29b812d44cc5a44
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 14:51:59 2018 +1100
- upstream commit
-
- %C is hashed; from klemens nanni ok markus
+ Comment out hexdump().
- Upstream-ID: 6ebed7b2e1b6ee5402a67875d74f5e2859d8f998
+ Nothing currently uses them but they cause conflicts on at least
+ FreeBSD, possibly others. ok djm@
-commit a66714508b86d6814e9055fefe362d9fe4d49ab3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 4 18:50:23 2017 +0000
+commit 5aea4aa522f61bb2f34c3055a7de203909dfae77
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 14:39:14 2018 +1100
- upstream commit
-
- exercise PermitOpen a little more thoroughly
-
- Upstream-Regress-ID: f41592334e227a4c1f9a983044522de4502d5eac
+ typo: missing ;
-commit 609ecc8e57eb88e2eac976bd3cae7f7889aaeff6
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Sep 26 22:39:25 2017 +0000
+commit cd3ab57f9b388f8b1abf601dc4d78ff82d83b75e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 14:37:06 2018 +1100
- upstream commit
-
- UsePrivilegeSeparation is gone, stop trying to test it.
+ Hook up flock() compat code.
- Upstream-Regress-ID: 796a5057cfd79456a20ea935cc53f6eb80ace191
+ Also a couple of minor changes: fail if we can't lock instead of
+ silently succeeding, and apply a couple of minor style fixes.
-commit 69bda0228861f3dacd4fb3d28b60ce9d103d254b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Oct 4 18:49:30 2017 +0000
+commit b087998d1ba90dd1ddb6bfdb17873dc3e7392798
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 14:27:02 2018 +1100
- upstream commit
-
- fix (another) problem in PermitOpen introduced during the
- channels.c refactor: the third and subsequent arguments to PermitOpen were
- being silently ignored; ok markus@
+ Import flock() compat from NetBSD.
- Upstream-ID: 067c89f1f53cbc381628012ba776d6861e6782fd
+ From NetBSD's src/trunk/tools/compat/flock.c, no OpenSSH changes yet.
-commit 66bf74a92131b7effe49fb0eefe5225151869dc5
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Oct 2 19:33:20 2017 +0000
+commit 89212533dde6798324e835b1499084658df4579e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 26 12:32:14 2018 +1100
- upstream commit
-
- Fix PermitOpen crash; spotted by benno@, ok dtucker@ deraadt@
+ Fix breakage when REGRESSTMP not set.
- Upstream-ID: c2cc84ffac070d2e1ff76182c70ca230a387983c
-
-commit d63b38160a59039708fd952adc75a0b3da141560
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Oct 1 10:32:25 2017 +1100
-
- update URL again
-
- I spotted a typo in the draft so uploaded a new version...
+ BUILDDIR is not set where used for REGRESSTMP, use make's CURDIR
+ instead. Pointed out by djm@.
-commit 6f64f596430cd3576c529f07acaaf2800aa17d58
+commit f885474137df4b89498c0b8834c2ac72c47aa4bd
Author: Damien Miller <djm@mindrot.org>
-Date: Sun Oct 1 10:01:56 2017 +1100
+Date: Mon Feb 26 12:18:14 2018 +1100
- sync release notes URL
+ XMSS-related files get includes.h
-commit 35ff70a04dd71663a5ac1e73b90d16d270a06e0d
+commit 612faa34c72e421cdc9e63f624526bae62d557cc
Author: Damien Miller <djm@mindrot.org>
-Date: Sun Oct 1 10:01:25 2017 +1100
+Date: Mon Feb 26 12:17:55 2018 +1100
- sync contrib/ssh-copy-id with upstream
+ object files end with .o - not .c
-commit 290843b8ede85f8b30bf29cd7dceb805c3ea5b66
+commit bda709b8e13d3eef19e69c2d1684139e3af728f5
Author: Damien Miller <djm@mindrot.org>
-Date: Sun Oct 1 09:59:19 2017 +1100
+Date: Mon Feb 26 12:17:22 2018 +1100
- update version in RPM spec files
+ avoid inclusion of deprecated selinux/flask.h
+
+ Use string_to_security_class() instead.
-commit 4e4e0bb223c5be88d87d5798c75cc6b0d4fef31d
+commit 2e396439365c4ca352cac222717d09b14f8a0dfd
Author: Damien Miller <djm@mindrot.org>
-Date: Sun Oct 1 09:58:24 2017 +1100
+Date: Mon Feb 26 11:48:27 2018 +1100
- update agent draft URL
+ updatedepend
-commit e4a798f001d2ecd8bf025c1d07658079f27cc604
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Sep 30 22:26:33 2017 +0000
+commit 1b11ea7c58cd5c59838b5fa574cd456d6047b2d4
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Fri Feb 23 15:58:37 2018 +0000
- upstream commit
+ upstream: Add experimental support for PQC XMSS keys (Extended
- openssh-7.6; ok deraadt@
+ Hash-Based Signatures) The code is not compiled in by default (see WITH_XMSS
+ in Makefile.inc) Joint work with stefan-lukas_gazdag at genua.eu See
+ https://tools.ietf.org/html/draft-irtf-cfrg-xmss-hash-based-signatures-12 ok
+ djm@
- Upstream-ID: a39c3a5b63a1baae109ae1ae4c7c34c2a59acde0
+ OpenBSD-Commit-ID: ef3eccb96762a5d6f135d7daeef608df7776a7ac
-commit 5fa1407e16e7e5fda9769d53b626ce39d5588d4d
+commit 7d330a1ac02076de98cfc8fda05353d57b603755
Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Wed Sep 27 06:45:53 2017 +0000
+Date: Fri Feb 23 07:38:09 2018 +0000
- upstream commit
-
- tweak EposeAuthinfo; diff from lars nooden
-
- tweaked by sthen; ok djm dtucker
+ upstream: some cleanup for BindInterface and ssh-keyscan;
- Upstream-ID: 8f2ea5d2065184363e8be7a0ba24d98a3b259748
+ OpenBSD-Commit-ID: 1a719ebeae22a166adf05bea5009add7075acc8c
-commit bba69c246f0331f657fd6ec97724df99fc1ad174
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Sep 28 16:06:21 2017 -0700
+commit c7b5a47e3b9db9a0f0198f9c90c705f6307afc2b
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 25 23:55:41 2018 +1100
- don't fatal ./configure for LibreSSL
+ Invert sense of getpgrp test.
+
+ AC_FUNC_GETPGRP tests if getpgrp(0) works, which it does if it's not
+ declared. Instead, test if the zero-arg version we want to use works.
-commit 04dc070e8b4507d9d829f910b29be7e3b2414913
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Sep 28 14:54:34 2017 -0700
+commit b39593a6de5290650a01adf8699c6460570403c2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 25 13:25:15 2018 +1100
- abort in configure when only openssl-1.1.x found
-
- We don't support openssl-1.1.x yet (see multiple threads on the
- openssh-unix-dev@ mailing list for the reason), but previously
- ./configure would accept it and the compilation would subsequently
- fail. This makes ./configure display an explicit error message and
- abort.
-
- ok dtucker@
+ Add no-op getsid implmentation.
-commit 74c1c3660acf996d9dc329e819179418dc115f2c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Sep 27 07:44:41 2017 +1000
+commit 11057564eb6ab8fd987de50c3d7f394c6f6632b7
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 25 11:22:57 2018 +1100
- Check for and handle calloc(p, 0) = NULL.
-
- On some platforms (AIX, maybe others) allocating zero bytes of memory
- via the various *alloc functions returns NULL, which is permitted
- by the standards. Autoconf has some macros for detecting this (with
- the exception of calloc for some reason) so use these and if necessary
- activate shims for them. ok djm@
+ bsd-statvfs: include sys/vfs.h, check for f_flags.
-commit 6a9481258a77b0b54b2a313d1761c87360c5f1f5
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Sep 21 19:18:12 2017 +0000
+commit e9dede06e5bc582a4aeb5b1cd5a7a640d7de3609
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 25 10:20:31 2018 +1100
- upstream commit
-
- test reverse dynamic forwarding with SOCKS
+ Handle calloc(0,x) where different from malloc.
- Upstream-Regress-ID: 95cf290470f7e5e2f691e4bc6ba19b91eced2f79
+ Configure assumes that if malloc(0) returns null then calloc(0,n)
+ also does. On some old platforms (SunOS4) malloc behaves as expected
+ (as determined by AC_FUNC_MALLOC) but calloc doesn't. Test for this
+ at configure time and activate the replacement function if found, plus
+ handle this case in rpl_calloc.
-commit 1b9f321605733754df60fac8c1d3283c89b74455
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Sep 26 16:55:55 2017 +1000
+commit 2eb4041493fd2635ffdc64a852d02b38c4955e0b
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 24 21:06:48 2018 +1100
- sync missing changes in dynamic-forward.sh
+ Add prototype for readv if needed.
-commit 44fc334c7a9ebdd08addb6d5fa005369897fddeb
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Sep 25 09:48:10 2017 +1000
+commit 6c8c9a615b6d31db8a87bc25033f053d5b0a831e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 24 20:46:37 2018 +1100
- Add minimal strsignal for platforms without it.
+ Check for raise and supply if needed.
-commit 218e6f98df566fb9bd363f6aa47018cb65ede196
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Sep 24 13:45:34 2017 +0000
+commit a9004425a032d7a7141a5437cfabfd02431e2a74
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 24 20:25:22 2018 +1100
- upstream commit
-
- fix inverted test on channel open failure path that
- "upgraded" a transient failure into a fatal error; reported by sthen and also
- seen by benno@; ok sthen@
+ Check for bzero and supply if needed.
- Upstream-ID: b58b3fbb79ba224599c6cd6b60c934fc46c68472
+ Since explicit_bzero uses it via an indirect it needs to be a function
+ not just a macro.
-commit c704f641f7b8777497dc82e81f2ac89afec7e401
+commit 1a348359e4d2876203b5255941bae348557f4f54
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Sep 24 09:50:01 2017 +0000
+Date: Fri Feb 23 05:14:05 2018 +0000
- upstream commit
+ upstream: Add ssh-keyscan -D option to make it print its results in
- write the correct buffer when tunnel forwarding; doesn't
- matter on OpenBSD (they are the same) but does matter on portable where we
- use an output filter to translate os-specific tun/tap headers
+ SSHFP format bz#2821, ok dtucker@
- Upstream-ID: f1ca94eff48404827b12e1d12f6139ee99a72284
+ OpenBSD-Commit-ID: 831446b582e0f298ca15c9d99c415c899e392221
-commit 55486f5cef117354f0c64f991895835077b7c7f7
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Sep 23 22:04:07 2017 +0000
+commit 3e19fb976a47b44b3d7c4f8355269f7f2c5dd82c
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Feb 23 04:18:46 2018 +0000
- upstream commit
+ upstream: Add missing braces.
- fix tunnel forwarding problem introduced in refactor;
- reported by stsp@ ok markus@
+ Caught by the tinderbox's -Werror=misleading-indentation, ok djm@
- Upstream-ID: 81a731cdae1122c8522134095d1a8b60fa9dcd04
+ OpenBSD-Commit-ID: d44656af594c3b2366eb87d6abcef83e1c88a6ca
-commit 609d7a66ce578abf259da2d5f6f68795c2bda731
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Thu Sep 21 19:16:53 2017 +0000
+commit b59162da99399d89bd57f71c170c0003c55b1583
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Feb 23 15:20:42 2018 +1100
- upstream commit
-
- Add 'reverse' dynamic forwarding which combines dynamic
- forwarding (-D) with remote forwarding (-R) where the remote-forwarded port
- expects SOCKS-requests.
-
- The SSH server code is unchanged and the parsing happens at the SSH
- clients side. Thus the full SOCKS-request is sent over the forwarded
- channel and the client parses c->output. Parsing happens in
- channel_before_prepare_select(), _before_ the select bitmask is
- computed in the pre[] handlers, but after network input processing
- in the post[] handlers.
-
- help and ok djm@
+ Check for ifaddrs.h for BindInterface.
- Upstream-ID: aa25a6a3851064f34fe719e0bf15656ad5a64b89
+ BindInterface required getifaddr and friends so disable if not available
+ (eg Solaris 10). We should be able to add support for some systems with
+ a bit more work but this gets the building again.
-commit 36945fa103176c00b39731e1fc1919a0d0808b81
+commit a8dd6fe0aa10b6866830b4688a73ef966f0aed88
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Feb 23 14:19:11 2018 +1100
+
+ space before tab in previous
+
+commit b5e9263c7704247f9624c8f5c458e9181fcdbc09
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Sep 20 05:19:00 2017 +0000
+Date: Fri Feb 9 03:40:22 2018 +0000
- upstream commit
+ upstream: Replace fatal with exit in the case that we do not have
- Use strsignal in debug message instead of casting for the
- benefit of portable where sig_atomic_t might not be int. "much nicer"
- deraadt@
+ $SUDO set. Prevents test failures when neither sudo nor doas are configured.
- Upstream-ID: 2dac6c1e40511c700bd90664cd263ed2299dcf79
+ OpenBSD-Regress-ID: 6a0464decc4f8ac7d6eded556a032b0fc521bc7b
-commit 3e8d185af326bf183b6f78597d5e3d2eeb2dc40e
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Tue Sep 19 12:10:30 2017 +0000
+commit 3e9d3192ad43758ef761c5b0aa3ac5ccf8121ef2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Feb 23 14:10:53 2018 +1100
- upstream commit
-
- Use explicit_bzero() instead of bzero() before free() to
- prevent the compiler from optimizing away the bzero() call. OK djm@
-
- Upstream-ID: cdc6197e64c9684c7250e23d60863ee1b53cef1d
+ Use portable syntax for REGRESSTMP.
-commit 5b8da1f53854c0923ec6e927e86709e4d72737b6
+commit 73282b61187883a2b2bb48e087fdda1d751d6059
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Sep 19 04:24:22 2017 +0000
+Date: Fri Feb 23 03:03:00 2018 +0000
- upstream commit
+ upstream: unbreak interop test after SSHv1 purge; patch from Colin
- fix use-after-free in ~^Z escape handler path, introduced
- in channels.c refactor; spotted by millert@ "makes sense" deraadt@
+ Watson via bz#2823
- Upstream-ID: 8fa2cdc65c23ad6420c1e59444b0c955b0589b22
+ OpenBSD-Regress-ID: 807d30a597756ed6612bdf46dfebca74f49cb31a
-commit a3839d8d2b89ff1a80cadd4dd654336710de2c9e
+commit f8985dde5f46aedade0373365cbf86ed3f1aead2
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Sep 18 12:03:24 2017 +0000
+Date: Fri Feb 9 03:42:57 2018 +0000
- upstream commit
+ upstream: Skip sftp-chroot test when SUDO not set instead of
- Prevent type mismatch warning in debug on platforms where
- sig_atomic_t != int. ok djm@
+ fatal().
- Upstream-ID: 306e2375eb0364a4c68e48f091739bea4f4892ed
+ OpenBSD-Regress-ID: cd4b5f1109b0dc09af4e5ea7d4968c43fbcbde88
-commit 30484e5e5f0b63d2c6ba32c6b85f06b6c6fa55fc
+commit df88551c02d4e3445c44ff67ba8757cff718609a
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Sep 18 09:41:52 2017 +0000
+Date: Fri Feb 9 03:40:22 2018 +0000
- upstream commit
+ upstream: Replace fatal with exit in the case that we do not have
- Add braces missing after channels refactor. ok markus@
+ $SUDO set. Prevents test failures when neither sudo nor doas are configured.
- Upstream-ID: 72ab325c84e010680dbc88f226e2aa96b11a3980
+ OpenBSD-Regress-ID: 6a0464decc4f8ac7d6eded556a032b0fc521bc7b
-commit b79569190b9b76dfacc6d996faa482f16e8fc026
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Sep 19 12:29:23 2017 +1000
+commit 3b252c20b19f093e87363de197f1100b79705dd3
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Feb 8 08:46:20 2018 +0000
- add freezero(3) replacement
+ upstream: some helpers to check verbose/quiet mode
- ok dtucker@
+ OpenBSD-Regress-ID: e736aac39e563f5360a0935080a71d5fdcb976de
-commit 161af8f5ec0961b10cc032efb5cc1b44ced5a92e
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Sep 19 10:18:56 2017 +1000
+commit ac2e3026bbee1367e4cda34765d1106099be3287
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Feb 23 02:34:33 2018 +0000
- move FORTIFY_SOURCE into hardening options group
+ upstream: Add BindInterface ssh_config directive and -B
- It's still on by default, but now it's possible to turn it off using
- --without-hardening. This is useful since it's known to cause problems
- with some -fsanitize options. ok dtucker@
+ command-line argument to ssh(1) that directs it to bind its outgoing
+ connection to the address of the specified network interface.
+
+ BindInterface prefers to use addresses that aren't loopback or link-
+ local, but will fall back to those if no other addresses of the
+ required family are available on that interface.
+
+ Based on patch by Mike Manning in bz#2820, ok dtucker@
+
+ OpenBSD-Commit-ID: c5064d285c2851f773dd736a2c342aa384fbf713
-commit 09eacf856e0fe1a6e3fe597ec8032b7046292914
-Author: bluhm@openbsd.org <bluhm@openbsd.org>
-Date: Wed Sep 13 14:58:26 2017 +0000
+commit fcdb9d777839a3fa034b3bc3067ba8c1f6886679
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Feb 19 00:55:02 2018 +0000
- upstream commit
+ upstream: emphasise that the hostkey rotation may send key types
- Print SKIPPED if sudo and doas configuration is missing.
- Prevents that running the regression test with wrong environment is reported
- as failure. Keep the fatal there to avoid interfering with other setups for
- portable ssh. OK dtucker@
+ that the client may not support, and that the client should simply disregard
+ such keys (this is what ssh does already).
- Upstream-Regress-ID: f0dc60023caef496ded341ac5aade2a606fa234e
+ OpenBSD-Commit-ID: 65f8ffbc32ac8d12be8f913d7c0ea55bef8622bf
-commit cdede10899892f25f1ccdccd7a3fe5e5ef0aa49a
+commit ce066f688dc166506c082dac41ca686066e3de5f
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 22 20:45:09 2018 +1100
+
+ Add headers for sys/audit.h.
+
+ On some older platforms (at least sunos4, probably others) sys/audit.h
+ requires some other headers. Patch from klausz at haus-gisela.de.
+
+commit 3fd2d2291a695c96a54269deae079bacce6e3fb9
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Mon Feb 19 18:37:40 2018 +1100
+
+ Add REGRESSTMP make var override.
+
+ Defaults to original location ($srcdir/regress) but allows overriding
+ if desired, eg a directory in /tmp.
+
+commit f8338428588f3ecb5243c86336eccaa28809f97e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 18 15:53:15 2018 +1100
+
+ Remove now-unused check for getrusage.
+
+ getrusage was used in ssh-rand-helper but that's now long gone.
+ Patch from klauszh at haus-gisela.de.
+
+commit 8570177195f6a4b3173c0a25484a83641ee3faa6
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Aug 7 03:52:55 2017 +0000
+Date: Fri Feb 16 04:43:11 2018 +0000
+
+ upstream: Don't send IUTF8 to servers that don't like them.
+
+ Some SSH servers eg "ConfD" drop the connection if the client sends the
+ new IUTF8 (RFC8160) terminal mode even if it's not set. Add a bug bit
+ for such servers and avoid sending IUTF8 to them. ok djm@
+
+ OpenBSD-Commit-ID: 26425855402d870c3c0a90491e72e2a8a342ceda
+
+commit f6dc2ba3c9d12be53057b9371f5109ec553a399f
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Fri Feb 16 17:32:28 2018 +1100
+
+ freezero should check for NULL.
+
+commit 680321f3eb46773883111e234b3c262142ff7c5b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Feb 16 02:40:45 2018 +0000
+
+ upstream: Mention recent DH KEX methods:
+
+ diffie-hellman-group14-sha256
+ diffie-hellman-group16-sha512
+ diffie-hellman-group18-sha512
+
+ From Jakub Jelen via bz#2826
+
+ OpenBSD-Commit-ID: 51bf769f06e55447f4bfa7306949e62d2401907a
+
+commit 88c50a5ae20902715f0fca306bb9c38514f71679
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Feb 16 02:32:40 2018 +0000
+
+ upstream: stop loading DSA keys by default, remove sshd_config
+
+ stanza and manpage bits; from Colin Watson via bz#2662, ok dtucker@
+
+ OpenBSD-Commit-ID: d33a849f481684ff655c140f5eb1b4acda8c5c09
+
+commit d2b3db2860c962927def39a52f67f1c23f7b201a
+Author: jsing@openbsd.org <jsing@openbsd.org>
+Date: Wed Feb 14 16:27:24 2018 +0000
+
+ upstream: Ensure that D mod (P-1) and D mod (Q-1) are calculated in
+
+ constant time.
+
+ This avoids a potential side channel timing leak.
+
+ ok djm@ markus@
+
+ OpenBSD-Commit-ID: 71ff3c16be03290e63d8edab8fac053d8a82968c
+
+commit 4270efad7048535b4f250f493d70f9acfb201593
+Author: jsing@openbsd.org <jsing@openbsd.org>
+Date: Wed Feb 14 16:03:32 2018 +0000
+
+ upstream: Some obvious freezero() conversions.
+
+ This also zeros an ed25519_pk when it was not being zeroed previously.
+
+ ok djm@ dtucker@
+
+ OpenBSD-Commit-ID: 5c196a3c85c23ac0bd9b11bcadaedd90b7a2ce82
+
+commit affa6ba67ffccc30b85d6e98f36eb5afd9386882
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 22:32:04 2018 +1100
+
+ Remove execute bit from modpipe.c.
+
+commit 9879dca438526ae6dfd656fecb26b0558c29c731
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 22:26:16 2018 +1100
+
+ Update prngd link to point to sourceforge.
+
+commit b6973fa5152b1a0bafd2417b7c3ad96f6e87d014
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 22:22:38 2018 +1100
+
+ Remove references to UNICOS.
+
+commit f1ca487940449f0b64f38f1da575078257609966
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 22:18:37 2018 +1100
+
+ Remove extra newline.
+
+commit 6d4e980f3cf27f409489cf89cd46c21501b13731
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 22:16:54 2018 +1100
+
+ OpenSSH's builtin entropy gathering is long gone.
+
+commit 389125b25d1a1d7f22e907463b7e8eca74af79ea
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 21:43:01 2018 +1100
+
+ Replace remaining mysignal() with signal().
+
+ These seem to have been missed during the replacement of mysignal
+ with #define signal in commit 5ade9ab. Both include the requisite
+ headers to pick up the #define.
+
+commit 265d88d4e61e352de6791733c8b29fa3d7d0c26d
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 20:06:19 2018 +1100
+
+ Remove remaining now-obsolete cvs $Ids.
+
+commit 015749e9b1d2f6e14733466d19ba72f014d0845c
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 15 17:01:54 2018 +1100
+
+ Regenerate dependencies after UNICOS removal.
+
+commit ddc0f3814881ea279a6b6d4d98e03afc60ae1ed7
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 13 09:10:46 2018 +1100
+
+ Remove UNICOS support.
+
+ The code required to support it is quite invasive to the mainline
+ code that is synced with upstream and is an ongoing maintenance burden.
+ Both the hardware and software are literal museum pieces these days and
+ we could not find anyone still running OpenSSH on one.
+
+commit 174bed686968494723e6db881208cc4dac0d020f
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 13 18:12:47 2018 +1100
+
+ Retpoline linker flag only needed for linking.
+
+commit 075e258c2cc41e1d7f3ea2d292c5342091728d40
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 13 17:36:43 2018 +1100
+
+ Default PidFile is sshd.pid not ssh.pid.
+
+commit 49f3c0ec47730ea264e2bd1e6ece11167d6384df
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 13 16:27:09 2018 +1100
+
+ Remove assigned-to-but-never-used variable.
+
+ 'p' was removed in previous change but I neglected to remove the
+ otherwise-unused assignment to it.
+
+commit b8bbff3b3fc823bf80c5ab226c94f13cb887d5b1
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Feb 13 03:36:56 2018 +0000
+
+ upstream: remove space before tab
+
+ OpenBSD-Commit-ID: 674edd214d0a7332dd4623c9cf8117301b012890
+
+commit 05046d907c211cb9b4cd21b8eff9e7a46cd6c5ab
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Feb 11 21:16:56 2018 +0000
+
+ upstream Don't reset signal handlers inside handlers.
+
+ The signal handlers from the original ssh1 code on which OpenSSH
+ is based assume unreliable signals and reinstall their handlers.
+ Since OpenBSD (and pretty much every current system) has reliable
+ signals this is not needed. In the unlikely even that -portable
+ is still being used on such systems we will deal with it in the
+ compat layer. ok deraadt@
+
+ OpenBSD-Commit-ID: f53a1015cb6908431b92116130d285d71589612c
+
+commit 3c51143c639ac686687c7acf9b373b8c08195ffb
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 13 09:07:29 2018 +1100
+
+ Whitespace sync with upstream.
+
+commit 19edfd4af746bedf0df17f01953ba8c6d3186eb7
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Tue Feb 13 08:25:46 2018 +1100
+
+ Whitespace sync with upstream.
+
+commit fbfa6f980d7460b3e12b0ce88ed3b6018edf4711
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 11 21:25:11 2018 +1300
+
+ Move signal compat code into bsd-signal.{c,h}
+
+commit 24d2a33bd3bf5170700bfdd8675498aa09a79eab
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 11 21:20:39 2018 +1300
+
+ Include headers for linux/if.h.
+
+ Prevents configure-time "present but cannot be compiled" warning.
+
+commit bc02181c24fc551aab85eb2cff0f90380928ef43
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 11 19:45:47 2018 +1300
+
+ Fix test for -z,retpolineplt linker flag.
+
+commit 3377df00ea3fece5293db85fe63baef33bf5152e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sun Feb 11 09:32:37 2018 +1100
+
+ Add checks for Spectre v2 mitigation (retpoline)
+
+ This adds checks for gcc and clang flags for mitigations for Spectre
+ variant 2, ie "retpoline". It'll automatically enabled if the compiler
+ supports it as part of toolchain hardening flag. ok djm@
+
+commit d9e5cf078ea5380da6df767bb1773802ec557ef0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Feb 10 09:25:34 2018 +0000
upstream commit
- Remove obsolete privsep=no fallback test.
+ constify some private key-related functions; based on
+ https://github.com/openssh/openssh-portable/pull/56 by Vincent Brillault
- Upstream-Regress-ID: 7d6e1baa1678ac6be50c2a1555662eb1047638df
+ OpenBSD-Commit-ID: dcb94a41834a15f4d00275cb5051616fdc4c988c
-commit ec218c105daa9f5b192f7aa890fdb2d4fdc4e9d8
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Aug 7 00:53:51 2017 +0000
+commit a7c38215d564bf98e8e9eb40c1079e3adf686f15
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Feb 10 09:03:54 2018 +0000
upstream commit
- Remove non-privsep test since disabling privsep is now
- deprecated.
+ Mention ServerAliveTimeout in context of TCPKeepAlives;
+ prompted by Christoph Anton Mitterer via github
- Upstream-Regress-ID: 77ad3f3d8d52e87f514a80f285c6c1229b108ce8
+ OpenBSD-Commit-ID: f0cf1b5bd3f1fbf41d71c88d75d93afc1c880ca2
-commit 239c57d5bc2253e27e3e6ad7ac52ec8c377ee24e
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jul 28 10:32:08 2017 +0000
+commit 62562ceae61e4f7cf896566592bb840216e71061
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Feb 10 06:54:38 2018 +0000
upstream commit
- Don't call fatal from stop_sshd since it calls cleanup
- which calls stop_sshd which will probably fail in the same way. Instead,
- just bail. Differentiate between sshd dying without cleanup and not shutting
- down.
+ clarify IgnoreUserKnownHosts; based on github PR from
+ Christoph Anton Mitterer.
- Upstream-Regress-ID: f97315f538618b349e2b0bea02d6b0c9196c6bc4
+ OpenBSD-Commit-ID: 4fff2c17620c342fb2f1f9c2d2e679aab3e589c3
-commit aea59a0d9f120f2a87c7f494a0d9c51eaa79b8ba
+commit 4f011daa4cada6450fa810f7563b8968639bb562
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 14 04:32:21 2017 +0000
+Date: Sat Feb 10 06:40:28 2018 +0000
upstream commit
- Revert commitid: gJtIN6rRTS3CHy9b.
-
- -------------
- identify the case where SSHFP records are missing but other DNS RR
- types are present and display a more useful error message for this
- case; patch by Thordur Bjornsson; bz#2501; ok dtucker@
- -------------
-
- This caused unexpected failures when VerifyHostKeyDNS=yes, SSHFP results
- are missing but the user already has the key in known_hosts
-
- Spotted by dtucker@
+ Shorter, more accurate explanation of
+ NoHostAuthenticationForLocalhost without the confusing example. Prompted by
+ Christoph Anton Mitterer via github and bz#2293.
- Upstream-ID: 97e31742fddaf72046f6ffef091ec0d823299920
-
-commit 871f1e4374420b07550041b329627c474abc3010
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Sep 12 18:01:35 2017 +1000
-
- adapt portable to channels API changes
+ OpenBSD-Commit-ID: 19dc96bea25b80d78d416b581fb8506f1e7b76df
-commit 4ec0bb9f9ad7b4eb0af110fa8eddf8fa199e46bb
+commit 77e05394af21d3f5faa0c09ed3855e4505a5cf9f
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Sep 12 07:55:48 2017 +0000
+Date: Sat Feb 10 06:15:12 2018 +0000
upstream commit
- unused variable
+ Disable RemoteCommand and RequestTTY in the ssh session
+ started by scp. sftp is already doing this. From Camden Narzt via github; ok
+ dtucker
- Upstream-ID: 2f9ba09f2708993d35eac5aa71df910dcc52bac1
+ OpenBSD-Commit-ID: 59e2611141c0b2ee579c6866e8eb9d7d8217bc6b
-commit 9145a73ce2ba30c82bbf91d7205bfd112529449f
+commit ca613249a00b64b2eea9f52d3834b55c28cf2862
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Sep 12 07:32:04 2017 +0000
+Date: Sat Feb 10 05:48:46 2018 +0000
upstream commit
- fix tun/tap forwarding case in previous
+ Refuse to create a certificate with an unusable number of
+ principals; Prompted by gdestuynder via github
- Upstream-ID: 43ebe37a930320e24bca6900dccc39857840bc53
+ OpenBSD-Commit-ID: 8cfae2451e8f07810e3e2546dfdcce66984cbd29
-commit 9f53229c2ac97dbc6f5a03657de08a1150a9ac7e
+commit b56ac069d46b6f800de34e1e935f98d050731d14
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Sep 12 06:35:31 2017 +0000
+Date: Sat Feb 10 05:43:26 2018 +0000
upstream commit
- Make remote channel ID a u_int
-
- Previously we tracked the remote channel IDs in an int, but this is
- strictly incorrect: the wire protocol uses uint32 and there is nothing
- in-principle stopping a SSH implementation from sending, say, 0xffff0000.
-
- In practice everyone numbers their channels sequentially, so this has
- never been a problem.
-
- ok markus@
+ fatal if we're unable to write all the public key; previously
+ we would silently ignore errors writing the comment and terminating newline.
+ Prompted by github PR from WillerZ; ok dtucker
- Upstream-ID: b9f4cd3dc53155b4a5c995c0adba7da760d03e73
+ OpenBSD-Commit-ID: 18fbfcfd4e8c6adbc84820039b64d70906e49831
-commit dbee4119b502e3f8b6cd3282c69c537fd01d8e16
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Sep 12 06:32:07 2017 +0000
+commit cdb10bd431f9f6833475c27e9a82ebb36fdb12db
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 11:18:38 2018 +1100
- upstream commit
+ Add changelog entry for binary strip change.
+
+commit fbddd91897cfaf456bfc2081f39fb4a2208a0ebf
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 11:14:54 2018 +1100
+
+ Remove unused variables.
+
+commit 937d96587df99c16c611d828cded292fa474a32b
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 11:12:45 2018 +1100
+
+ Don't strip binaries so debuginfo gets built.
- refactor channels.c
+ Tell install not to strip binaries during package creation so that the
+ debuginfo package can be built.
+
+commit eb0865f330f59c889ec92696b97bd397090e720c
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 10:33:11 2018 +1100
+
+ Fix bogus dates in changelog.
+
+commit 7fbde1b34c1f6c9ca9e9d10805ba1e5e4538e165
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 10:25:15 2018 +1100
+
+ Remove SSH1 from description.
+
+commit 9c34a76f099c4e0634bf6ecc2f40ce93925402c4
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 10:19:16 2018 +1100
+
+ Add support for compat-openssl10 build dep.
+
+commit 04f4e8193cb5a5a751fcc356bd6656291fec539e
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 09:57:04 2018 +1100
+
+ Add leading zero so it'll work when rhel not set.
- Move static state to a "struct ssh_channels" that is allocated at
- runtime and tracked as a member of struct ssh.
+ When rhel is not set it will error out with "bad if". Add leading zero
+ as per https://fedoraproject.org/wiki/Packaging:DistTag so it'll work
+ on non-RHEL.
+
+commit 12abd67a6af28476550807a443b38def2076bb92
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Sat Feb 10 09:56:34 2018 +1100
+
+ Update openssl-devel dependency.
+
+commit b33e7645f8813719d7f9173fef24463c8833ebb3
+Author: nkadel <nkadel@gmail.com>
+Date: Sun Nov 16 18:19:58 2014 -0500
+
+ Add mandir with-mandir' for RHEL 5 compatibility.
- Explicitly pass "struct ssh" to all channels functions.
+ Activate '--mandir' and '--with-mandir' settings in setup for RHEL
+ 5 compatibility.
+
+commit 94f8bf360eb0162e39ddf39d69925c2e93511e40
+Author: nkadel <nkadel@gmail.com>
+Date: Sun Nov 16 18:18:51 2014 -0500
+
+ Discard 'K5DIR' reporting.
- Replace use of the legacy packet APIs in channels.c.
+ It does not work inside 'mock' build environment.
+
+commit bb7e54dbaf34b70b3e57acf7982f3a2136c94ee5
+Author: nkadel <nkadel@gmail.com>
+Date: Sun Nov 16 18:17:15 2014 -0500
+
+ Add 'dist' to 'rel' for OS specific RPM names.
+
+commit 87346f1f57f71150a9b8c7029d8c210e27027716
+Author: nkadel <nkadel@gmail.com>
+Date: Sun Nov 16 14:17:38 2014 -0500
+
+ Add openssh-devel >= 0.9.8f for redhat spec file.
+
+commit bec1478d710866d3c1b119343a35567a8fc71ec3
+Author: nkadel <nkadel@gmail.com>
+Date: Sun Nov 16 13:10:24 2014 -0500
+
+ Enhance BuildRequires for openssh-x11-askpass.
+
+commit 3104fcbdd3c70aefcb0cdc3ee24948907db8dc8f
+Author: nkadel <nkadel@gmail.com>
+Date: Sun Nov 16 13:04:14 2014 -0500
+
+ Always include x11-ssh-askpass SRPM.
- Rework sshd_config PermitOpen handling: previously the configuration
- parser would call directly into the channels layer. After the refactor
- this is not possible, as the channels structures are allocated at
- connection time and aren't available when the configuration is parsed.
- The server config parser now tracks PermitOpen itself and explicitly
- configures the channels code later.
+ Always include x11-ssh-askpass tarball in redhat SRPM, even if unused.
+
+commit c61d0d038d58eebc365f31830be6e04ce373ad1b
+Author: Damien Miller <djm@mindrot.org>
+Date: Sat Feb 10 09:43:12 2018 +1100
+
+ this is long unused; prompted by dtucker@
+
+commit 745771fb788e41bb7cdad34e5555bf82da3af7ed
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Feb 9 02:37:36 2018 +0000
+
+ upstream commit
- ok markus@
+ Remove unused sKerberosTgtPassing from enum. From
+ calestyo via github pull req #11, ok djm@
- Upstream-ID: 11828f161656b965cc306576422613614bea2d8f
+ OpenBSD-Commit-ID: 1008f8870865a7c4968b7aed402a0a9e3e5b9540
-commit abd59663df37a42152e37980113ccaa405b9a282
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Sep 7 23:48:09 2017 +0000
+commit 1f385f55332db830b0ae22a7663b98279ca2d657
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Thu Feb 8 04:12:32 2018 +0000
upstream commit
- typo in comment
+ Rename struct umac_ctx to umac128_ctx too. In portable
+ some linkers complain about two symbols with the same name having differing
+ sizes. ok djm@
- Upstream-ID: a93b1e6f30f1f9b854b5b964b9fd092d0c422c47
+ OpenBSD-Commit-ID: cbebf8bdd3310a9795b4939a1e112cfe24061ca3
-commit 149a8cd24ce9dd47c36f571738681df5f31a326c
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Sep 4 06:34:43 2017 +0000
+commit f1f047fb031c0081dbc8738f05bf5d4cc47acadf
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Feb 7 22:52:45 2018 +0000
upstream commit
- tweak previous;
+ ssh_free checks for and handles NULL args, remove NULL
+ checks from remaining callers. ok djm@
- Upstream-ID: bb8cc40b61b15f6a13d81da465ac5bfc65cbfc4b
+ OpenBSD-Commit-ID: bb926825c53724c069df68a93a2597f9192f7e7b
-commit ec9d22cc251cc5acfe7b2bcef9cc7a1fe0e949d8
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Sep 8 12:44:13 2017 +1000
+commit aee49b2a89b6b323c80dd3b431bd486e51f94c8c
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Thu Feb 8 12:36:22 2018 +1100
- Fuzzer harnesses for sig verify and pubkey parsing
+ Set SO_REUSEADDR in regression test netcat.
- These are some basic clang libfuzzer harnesses for signature
- verification and public key parsing. Some assembly (metaphorical)
- required.
+ Sometimes multiplex tests fail on Solaris with "netcat: local_listen:
+ Address already in use" which is likely due to previous invocations
+ leaving the port in TIME_WAIT. Set SO_REUSEADDR (in addition to
+ SO_REUSEPORT which is alread set on platforms that support it). ok djm@
-commit de35c382894964a896a63ecd5607d3a3b93af75d
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Sep 8 12:38:31 2017 +1000
+commit 1749991c55bab716877b7c687cbfbf19189ac6f1
+Author: jsing@openbsd.org <jsing@openbsd.org>
+Date: Wed Feb 7 05:17:56 2018 +0000
- Give configure ability to set CFLAGS/LDFLAGS later
-
- Some CFLAGS/LDFLAGS may disrupt the configure script's operation,
- in particular santization and fuzzer options that break assumptions
- about memory and file descriptor dispositions.
+ upstream commit
- This adds two flags to configure --with-cflags-after and
- --with-ldflags-after that allow specifying additional compiler and
- linker options that are added to the resultant Makefiles but not
- used in the configure run itself.
+ Convert some explicit_bzero()/free() calls to freezero().
- E.g.
+ ok deraadt@ dtucker@
- env CC=clang-3.9 ./configure \
- --with-cflags-after=-fsantize=address \
- --with-ldflags-after="-g -fsanitize=address"
+ OpenBSD-Commit-ID: f566ab99149650ebe58b1d4b946ea726c3829609
-commit 22376d27a349f62c502fec3396dfe0fdcb2a40b7
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Sep 3 23:33:13 2017 +0000
+commit 94ec2b69d403f4318b7a0d9b17f8bc3efbf4d0d2
+Author: jsing@openbsd.org <jsing@openbsd.org>
+Date: Wed Feb 7 05:15:49 2018 +0000
upstream commit
- Expand ssh_config's StrictModes option with two new
- settings:
-
- StrictModes=accept-new will automatically accept hitherto-unseen keys
- but will refuse connections for changed or invalid hostkeys.
+ Remove some #ifdef notyet code from OpenSSL 0.9.8 days.
- StrictModes=off is the same as StrictModes=no
+ These functions have never appeared in OpenSSL and are likely never to do
+ so.
- Motivation:
+ "kill it with fire" djm@
- StrictModes=no combines two behaviours for host key processing:
- automatically learning new hostkeys and continuing to connect to hosts
- with invalid/changed hostkeys. The latter behaviour is quite dangerous
- since it removes most of the protections the SSH protocol is supposed to
- provide.
+ OpenBSD-Commit-ID: fee9560e283fd836efc2631ef381658cc673d23e
+
+commit 7cd31632e3a6607170ed0c9ed413a7ded5b9b377
+Author: jsing@openbsd.org <jsing@openbsd.org>
+Date: Wed Feb 7 02:06:50 2018 +0000
+
+ upstream commit
- Quite a few users want to automatically learn hostkeys however, so
- this makes that feature available with less danger.
+ Remove all guards for calls to OpenSSL free functions -
+ all of these functions handle NULL, from at least OpenSSL 1.0.1g onwards.
- At some point in the future, StrictModes=no will change to be a synonym
- for accept-new, with its current behaviour remaining available via
- StrictModes=off.
+ Prompted by dtucker@ asking about guards for RSA_free(), when looking at
+ openssh-portable pr#84 on github.
- bz#2400, suggested by Michael Samuel; ok markus
+ ok deraadt@ dtucker@
- Upstream-ID: 0f55502bf75fc93a74fb9853264a8276b9680b64
+ OpenBSD-Commit-ID: 954f1c51b94297d0ae1f749271e184141e0cadae
-commit ff3c42384033514e248ba5d7376aa033f4a2b99a
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Sep 1 15:41:26 2017 +0000
+commit 3c000d57d46882eb736c6563edfc4995915c24a2
+Author: Darren Tucker <dtucker@dtucker.net>
+Date: Wed Feb 7 09:19:38 2018 +1100
- upstream commit
-
- remove blank line;
+ Remove obsolete "Smartcard support" message
- Upstream-ID: 2f46b51a0ddb3730020791719e94d3e418e9f423
+ The configure checks that populated $SCARD_MSG were removed in commits
+ 7ea845e4 and d8f60022 when the smartcard support was replaced with
+ PKCS#11.
-commit b828605d51f57851316d7ba402b4ae06cf37c55d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 1 05:53:56 2017 +0000
+commit 3e615090de0ce36a833d811e01c28aec531247c4
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Tue Feb 6 06:01:54 2018 +0000
upstream commit
- identify the case where SSHFP records are missing but
- other DNS RR types are present and display a more useful error message for
- this case; patch by Thordur Bjornsson; bz#2501; ok dtucker@
+ Replace "trojan horse" with the correct term (MITM).
+ From maikel at predikkta.com via bz#2822, ok markus@
- Upstream-ID: 8f7a5a8344f684823d8317a9708b63e75be2c244
+ OpenBSD-Commit-ID: e86ac64c512057c89edfadb43302ac0aa81a6c53
-commit 8042bad97e2789a50e8f742c3bcd665ebf0add32
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Sep 1 05:50:48 2017 +0000
+commit 3484380110d437c50e17f87d18544286328c75cb
+Author: tb@openbsd.org <tb@openbsd.org>
+Date: Mon Feb 5 05:37:46 2018 +0000
upstream commit
- document available AuthenticationMethods; bz#2453 ok
- dtucker@
+ Add a couple of non-negativity checks to avoid close(-1).
- Upstream-ID: 2c70576f237bb699aff59889dbf2acba4276d3d0
+ ok djm
+
+ OpenBSD-Commit-ID: 4701ce0b37161c891c838d0931305f1d37a50880
-commit 71e5a536ec815d542b199f2ae6d646c0db9f1b58
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Aug 30 03:59:08 2017 +0000
+commit 5069320be93c8b2a6584b9f944c86f60c2b04e48
+Author: tb@openbsd.org <tb@openbsd.org>
+Date: Mon Feb 5 05:36:49 2018 +0000
upstream commit
- pass packet state down to some of the channels function
- (more to come...); ok markus@
+ The file descriptors for socket, stdin, stdout and stderr
+ aren't necessarily distinct, so check if they are the same to avoid closing
+ the same fd several times.
- Upstream-ID: d8ce7a94f4059d7ac1e01fb0eb01de0c4b36c81b
+ ok djm
+
+ OpenBSD-Commit-ID: 60d71fd22e9a32f5639d4ba6e25a2f417fc36ac1
-commit 6227fe5b362239c872b91bbdee4bf63cf85aebc5
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue Aug 29 13:05:58 2017 +0000
+commit 2b428f90ea1b21d7a7c68ec1ee334253b3f9324d
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Feb 5 04:02:53 2018 +0000
upstream commit
- sort options;
+ I accidentially a word
- Upstream-ID: cf21d68cf54e81968bca629aaeddc87f0c684f3c
+ OpenBSD-Commit-ID: 4547ee713fa941da861e83ae7a3e6432f915e14a
-commit 530591a5795a02d01c78877d58604723918aac87
-Author: dlg@openbsd.org <dlg@openbsd.org>
-Date: Tue Aug 29 09:42:29 2017 +0000
+commit 130283d5c2545ff017c2162dc1258c5354e29399
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jan 25 03:34:43 2018 +0000
upstream commit
- add a -q option to ssh-add to make it quiet on success.
-
- if you want to silence ssh-add without this you generally redirect
- the output to /dev/null, but that can hide error output which you
- should see.
+ certificate options are case-sensitive; fix case on one
+ that had it wrong.
- ok djm@
+ move a badly-place sentence to a less bad place
- Upstream-ID: 2f31b9b13f99dcf587e9a8ba443458e6c0d8997c
+ OpenBSD-Commit-ID: 231e516bba860699a1eece6d48532d825f5f747b
-commit a54eb27dd64b5eca3ba94e15cec3535124bd5029
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Aug 27 00:38:41 2017 +0000
+commit 89f09ee68730337015bf0c3f138504494a34e9a6
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Jan 24 12:20:44 2018 +1100
+
+ crypto_api.h needs includes.h
+
+commit c9c1bba06ad1c7cad8548549a68c071bd807af60
+Author: stsp@openbsd.org <stsp@openbsd.org>
+Date: Tue Jan 23 20:00:58 2018 +0000
upstream commit
- Increase the buffer sizes for user prompts to ensure that
- they won't be truncated by snprintf. Based on patch from cjwatson at
- debian.org via bz#2768, ok djm@
+ Fix a logic bug in sshd_exchange_identification which
+ prevented clients using major protocol version 2 from connecting to the
+ server. ok millert@
- Upstream-ID: 6ffacf1abec8f40b469de5b94bfb29997d96af3e
+ OpenBSD-Commit-ID: 8668dec04586e27f1c0eb039ef1feb93d80a5ee9
-commit dd9d9b3381a4597b840d480b043823112039327e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Aug 28 16:48:27 2017 +1000
+commit a60c5dcfa2538ffc94dc5b5adb3db5b6ed905bdb
+Author: stsp@openbsd.org <stsp@openbsd.org>
+Date: Tue Jan 23 18:33:49 2018 +0000
- Switch Capsicum header to sys/capsicum.h.
+ upstream commit
- FreeBSD's <sys/capability.h> was renamed to <sys/capsicum.h> in 2014 to
- avoid future conflicts with POSIX capabilities (the last release that
- didn't have it was 9.3) so switch to that. Patch from des at des.no.
-
-commit f5e917ab105af5dd6429348d9bc463e52b263f92
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Aug 27 08:55:40 2017 +1000
-
- Add missing includes for bsd-err.c.
+ Add missing braces; fixes 'write: Socket is not
+ connected' error in ssh. ok deraadt@
- Patch from cjwatson at debian.org via bz#2767.
+ OpenBSD-Commit-ID: db73a3a9e147722d410866cac34d43ed52e1ad24
-commit 878e029797cfc9754771d6f6ea17f8c89e11d225
+commit 20d53ac283e1c60245ea464bdedd015ed9b38f4a
Author: Damien Miller <djm@mindrot.org>
-Date: Fri Aug 25 13:25:01 2017 +1000
+Date: Tue Jan 23 16:49:43 2018 +1100
- Split platform_sys_dir_uid into its own file
-
- platform.o is too heavy for libssh.a use; it calls into the server on
- many platforms. Move just the function needed by misc.c into its own
- file.
+ rebuild depends
-commit 07949bfe9133234eddd01715592aa0dde67745f0
+commit 552ea155be44f9c439c1f9f0c38f9e593428f838
Author: Damien Miller <djm@mindrot.org>
-Date: Wed Aug 23 20:13:18 2017 +1000
+Date: Tue Jan 23 16:49:22 2018 +1100
- misc.c needs functions from platform.c now
+ one SSH_BUG_BANNER instance that got away
-commit b074c3c3f820000a21953441cea7699c4b17d72f
+commit 14b5c635d1190633b23ac3372379517fb645b0c2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 18 05:48:04 2017 +0000
+Date: Tue Jan 23 05:27:21 2018 +0000
upstream commit
- add a "quiet" flag to exited_cleanly() that supresses
- errors about exit status (failure due to signal is still reported)
-
- Upstream-ID: db85c39c3aa08e6ff67fc1fb4ffa89f807a9d2f0
-
-commit de4ae07f12dabf8815ecede54235fce5d22e3f63
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 18 05:36:45 2017 +0000
-
- upstream commit
+ Drop compatibility hacks for some ancient SSH
+ implementations, including ssh.com <=2.* and OpenSSH <= 3.*.
- Move several subprocess-related functions from various
- locations to misc.c. Extend subprocess() to offer a little more control over
- stdio disposition.
+ These versions were all released in or before 2001 and predate the
+ final SSH RFCs. The hacks in question aren't necessary for RFC-
+ compliant SSH implementations.
- feedback & ok dtucker@
+ ok markus@
- Upstream-ID: 3573dd7109d13ef9bd3bed93a3deb170fbfce049
+ OpenBSD-Commit-ID: 4be81c67db57647f907f4e881fb9341448606138
-commit 643c2ad82910691b2240551ea8b14472f60b5078
+commit 7c77991f5de5d8475cbeb7cbb06d0c7d1611d7bb
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Aug 12 06:46:01 2017 +0000
+Date: Tue Jan 23 05:17:04 2018 +0000
upstream commit
- make "--" before the hostname terminate command-line
- option processing completely; previous behaviour would not prevent further
- options appearing after the hostname (ssh has a supported options after the
- hostname for >20 years, so that's too late to change).
-
- ok deraadt@
+ try harder to preserve errno during
+ ssh_connect_direct() to make the final error message possibly accurate;
+ bz#2814, ok dtucker@
- Upstream-ID: ef5ee50571b98ad94dcdf8282204e877ec88ad89
+ OpenBSD-Commit-ID: 57de882cb47381c319b04499fef845dd0c2b46ca
-commit 0f3455356bc284d7c6f4d3c1614d31161bd5dcc2
+commit 9e9c4a7e57b96ab29fe6d7545ed09d2e5bddbdec
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Aug 12 06:42:52 2017 +0000
+Date: Tue Jan 23 05:12:12 2018 +0000
upstream commit
- Switch from aes256-cbc to aes256-ctr for encrypting
- new-style private keys. The latter having the advantage of being supported
- for no-OpenSSL builds; bz#2754 ok markus@
+ unbreak support for clients that advertise a protocol
+ version of "1.99" (indicating both v2 and v1 support). Busted by me during
+ SSHv1 purge in r1.358; bz2810, ok dtucker
- Upstream-ID: 54179a2afd28f93470471030567ac40431e56909
+ OpenBSD-Commit-ID: e8f9c2bee11afc16c872bb79d6abe9c555bd0e4b
-commit c4972d0a9bd6f898462906b4827e09b7caea2d9b
+commit fc21ea97968264ad9bb86b13fedaaec8fd3bf97d
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 11 04:47:12 2017 +0000
+Date: Tue Jan 23 05:06:25 2018 +0000
upstream commit
- refuse to a private keys when its corresponding .pub key
- does not match. bz#2737 ok dtucker@
+ don't attempt to force hostnames that are addresses to
+ lowercase, but instead canonicalise them through getnameinfo/getaddrinfo to
+ remove ambiguities (e.g. ::0001 => ::1) before they are matched against
+ known_hosts; bz#2763, ok dtucker@
- Upstream-ID: 54ff5e2db00037f9db8d61690f26ef8f16e0d913
+ OpenBSD-Commit-ID: ba0863ff087e61e5c65efdbe53be3cb92c9aefa0
-commit 4b3ecbb663c919132dddb3758e17a23089413519
+commit d6364f6fb1a3d753d7ca9bf15b2adce961324513
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Aug 11 04:41:08 2017 +0000
+Date: Tue Jan 23 05:01:15 2018 +0000
upstream commit
- don't print verbose error message when ssh disconnects
- under sftp; bz#2750; ok dtucker@
+ avoid modifying pw->pw_passwd; let endpwent() clean up
+ for us, but keep a scrubbed copy; bz2777, ok dtucker@
- Upstream-ID: 6d83708aed77b933c47cf155a87dc753ec01f370
+ OpenBSD-Commit-ID: 715afc0f59c6b82c4929a73279199ed241ce0752
-commit 42a8f8bc288ef8cac504c5c73f09ed610bc74a34
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Aug 11 04:16:35 2017 +0000
+commit a69bbb07cd6fb4dfb9bdcacd370ab26d0a2b4215
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Sat Jan 13 00:24:09 2018 +0000
upstream commit
- Tweak previous keepalive commit: if last_time + keepalive
- <= now instead of just "<" so client_alive_check will fire if the select
- happens to return on exact second of the timeout. ok djm@
+ clarify authorship; prodded by and ok markus@
- Upstream-ID: e02756bd6038d11bb8522bfd75a4761c3a684fcc
+ OpenBSD-Commit-ID: e1938eee58c89b064befdabe232835fa83bb378c
-commit b60ff20051ef96dfb207b6bfa45c0ad6c34a542a
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Aug 11 03:58:36 2017 +0000
+commit 04214b30be3d3e73a01584db4e040d5ccbaaddd4
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jan 8 15:37:21 2018 +0000
upstream commit
- Keep track of the last time we actually heard from the
- client and use this to also schedule a client_alive_check(). Prevents
- activity on a forwarded port from indefinitely preventing the select timeout
- so that client_alive_check() will eventually (although not optimally) be
- called.
-
- Analysis by willchan at google com via bz#2756, feedback & ok djm@
+ group shared source files (e.g. SRCS_KEX) and allow
+ compilation w/o OPENSSL ok djm@
- Upstream-ID: c08721e0bbda55c6d18e2760f3fe1b17fb71169e
+ OpenBSD-Commit-ID: fa728823ba21c4b45212750e1d3a4b2086fd1a62
-commit 94bc1e7ffba3cbdea8c7dcdab8376bf29283128f
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 28 14:50:59 2017 +1000
+commit 25cf9105b849932fc3b141590c009e704f2eeba6
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jan 8 15:21:49 2018 +0000
- Expose list of completed auth methods to PAM
+ upstream commit
- bz#2408; ok dtucker@
+ move subprocess() so scp/sftp do not need uidswap.o; ok
+ djm@
+
+ OpenBSD-Commit-ID: 6601b8360388542c2e5fef0f4085f8e54750bea8
-commit c78e6eec78c88acf8d51db90ae05a3e39458603d
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 21 14:38:16 2017 +1000
+commit b0d34132b3ca26fe94013f01d7b92101e70b68bb
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jan 8 15:18:46 2018 +0000
- fix problems in tunnel forwarding portability code
+ upstream commit
- This fixes a few problems in the tun forwarding code, mostly to do
- with host/network byte order confusion.
+ switch ssh-pkcs11-helper to new API; ok djm@
- Based on a report and patch by stepe AT centaurus.uberspace.de;
- bz#2735; ok dtucker@
+ OpenBSD-Commit-ID: e0c0ed2a568e25b1d2024f3e630f3fea837c2a42
-commit 2985d4062ebf4204bbd373456a810d558698f9f5
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Jul 25 09:22:25 2017 +0000
+commit ec4a9831184c0c6ed5f7f0cfff01ede5455465a3
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jan 8 15:15:36 2018 +0000
upstream commit
- Make WinSCP patterns for SSH_OLD_DHGEX more specific to
- exclude WinSCP 5.10.x and up. bz#2748, from martin at winscp.net, ok djm@
+ split client/server kex; only ssh-keygen needs
+ uuencode.o; only scp/sftp use progressmeter.o; ok djm@
- Upstream-ID: 6fd7c32e99af3952db007aa180e73142ddbc741a
+ OpenBSD-Commit-ID: f2c9feb26963615c4fece921906cf72e248b61ee
-commit 9f0e44e1a0439ff4646495d5735baa61138930a9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jul 24 04:34:28 2017 +0000
+commit ec77efeea06ac62ee1d76fe0b3225f3000775a9e
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jan 8 15:15:17 2018 +0000
upstream commit
- g/c unused variable; make a little more portable
+ only ssh-keygen needs uuencode.o; only scp/sftp use
+ progressmeter.o
- Upstream-ID: 3f5980481551cb823c6fb2858900f93fa9217dea
+ OpenBSD-Commit-ID: a337e886a49f96701ccbc4832bed086a68abfa85
-commit 51676ec61491ec6d7cbd06082034e29b377b3bf6
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Jul 23 23:37:02 2017 +0000
+commit 25aae35d3d6ee86a8c4c0b1896acafc1eab30172
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Mon Jan 8 15:14:44 2018 +0000
upstream commit
- Allow IPQoS=none in ssh/sshd to not set an explicit
- ToS/DSCP value and just use the operating system default; ok dtucker@
+ uuencode.h is not used
- Upstream-ID: 77906ff8c7b660b02ba7cb1e47b17d66f54f1f7e
+ OpenBSD-Commit-ID: 238eb4659f3c119904326b9e94a5e507a912796c
-commit 6c1fbd5a50d8d2415f06c920dd3b1279b741072d
+commit 4f29309c4cb19bcb1774931db84cacc414f17d29
Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 21 14:24:26 2017 +1000
+Date: Wed Jan 3 19:50:43 2018 +1100
- mention libedit
+ unbreak fuzz harness
-commit dc2bd308768386b02c7337120203ca477e67ba62
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Jul 19 08:30:41 2017 +0000
+commit f6b50bf84dc0b61f22c887c00423e0ea7644e844
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Dec 21 05:46:35 2017 +0000
upstream commit
- fix support for unknown key types; ok djm@
+ another libssh casualty
- Upstream-ID: 53fb29394ed04d616d65b3748dee5aa06b07ab48
+ OpenBSD-Regress-ID: 839b970560246de23e7c50215095fb527a5a83ec
-commit fd0e8fa5f89d21290b1fb5f9d110ca4f113d81d9
+commit 5fb4fb5a0158318fb8ed7dbb32f3869bbf221f13
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jul 19 01:15:02 2017 +0000
+Date: Thu Dec 21 03:01:49 2017 +0000
upstream commit
- switch from select() to poll() for the ssh-agent
- mainloop; ok markus
+ missed one (unbreak after ssh/lib removal)
- Upstream-ID: 4a94888ee67b3fd948fd10693973beb12f802448
+ OpenBSD-Regress-ID: cfdd132143131769e2d2455e7892b5d55854c322
-commit b1e72df2b813ecc15bd0152167bf4af5f91c36d3
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jul 14 03:18:21 2017 +0000
+commit e6c4134165d05447009437a96e7201276688807f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Dec 21 00:41:22 2017 +0000
upstream commit
- Make ""Killed by signal 1" LogLevel verbose so it's not
- shown at the default level. Prevents it from appearing during ssh -J and
- equivalent ProxyCommand configs. bz#1906, bz#2744, feedback&ok markus@
+ unbreak unit tests after removal of src/usr.bin/ssh/lib
- Upstream-ID: debfaa7e859b272246c2f2633335d288d2e2ae28
+ OpenBSD-Regress-ID: 3a79760494147b20761cbd2bd5c20e86c63dc8f9
-commit 1f3d202770a08ee6752ed2a234b7ca6f180eb498
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Thu Jul 13 19:16:33 2017 +0000
+commit d45d69f2a937cea215c7f0424e5a4677b6d8c7fe
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Dec 21 00:00:28 2017 +0000
upstream commit
- man pages with pseudo synopses which list filenames end
- up creating very ugly output in man -k; after some discussion with ingo, we
- feel the simplest fix is to remove such SYNOPSIS sections: the info is hardly
- helpful at page top, is contained already in FILES, and there are
- sufficiently few that just zapping them is simple;
-
- ok schwarze, who also helpfully ran things through a build to check
- output;
+ revert stricter key type / signature type checking in
+ userauth path; too much software generates inconsistent messages, so we need
+ a better plan.
- Upstream-ID: 3e211b99457e2f4c925c5927d608e6f97431336c
+ OpenBSD-Commit-ID: 4a44ddc991c803c4ecc8f1ad40e0ab4d22e1c519
-commit 7f13a4827fb28957161de4249bd6d71954f1f2ed
-Author: espie@openbsd.org <espie@openbsd.org>
-Date: Mon Jul 10 14:09:59 2017 +0000
+commit c5a6cbdb79752f7e761074abdb487953ea6db671
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue Dec 19 00:49:30 2017 +0000
upstream commit
- zap redundant Makefile variables. okay djm@
+ explicitly test all key types and their certificate
+ counterparts
- Upstream-ID: e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604
+ refactor a little
+
+ OpenBSD-Regress-ID: e9ecd5580821b9ef8b7106919c6980d8e45ca8c4
-commit dc44dd3a9e2c9795394e6a7e1e71c929cbc70ce0
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Jul 8 18:32:54 2017 +0000
+commit f689adb7a370b5572612d88be9837ca9aea75447
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Dec 11 11:41:56 2017 +0000
upstream commit
- slightly rework previous, to avoid an article issue;
+ use cmp in a loop instead of diff -N to compare
+ directories. The former works on more platforms for Portable.
- Upstream-ID: 15a315f0460ddd3d4e2ade1f16d6c640a8c41b30
+ OpenBSD-Regress-ID: c3aa72807f9c488e8829a26ae50fe5bcc5b57099
-commit 853edbe057a84ebd0024c8003e4da21bf2b469f7
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jul 7 03:53:12 2017 +0000
+commit 748dd8e5de332b24c40f4b3bbedb902acb048c98
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Dec 19 16:17:59 2017 +1100
- upstream commit
-
- When generating all hostkeys (ssh-keygen -A), clobber
- existing keys if they exist but are zero length. zero-length keys could
- previously be made if ssh-keygen failed part way through generating them, so
- avoid that case too. bz#2561 reported by Krzysztof Cieplucha; ok dtucker@
-
- Upstream-ID: f662201c28ab8e1f086b5d43c59cddab5ade4044
+ remove blocks.c from Makefile
-commit 43616876ba68a2ffaece6a6c792def4b039f2d6e
+commit 278856320520e851063b06cef6ef1c60d4c5d652
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jul 1 22:55:44 2017 +0000
+Date: Tue Dec 19 00:24:34 2017 +0000
upstream commit
- actually remove these files
+ include signature type and CA key (if applicable) in some
+ debug messages
- Upstream-ID: 1bd41cba06a7752de4df304305a8153ebfb6b0ac
+ OpenBSD-Commit-ID: b71615cc20e78cec7105bb6e940c03ce9ae414a5
-commit 83fa3a044891887369ce8b487ce88d713a04df48
+commit 7860731ef190b52119fa480f8064ab03c44a120a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jul 1 13:50:45 2017 +0000
+Date: Mon Dec 18 23:16:23 2017 +0000
upstream commit
- remove post-SSHv1 removal dead code from rsa.c and merge
- the remaining bit that it still used into ssh-rsa.c; ok markus
+ unbreak hostkey rotation; attempting to sign with a
+ desired signature algorithm of kex->hostkey_alg is incorrect when the key
+ type isn't capable of making those signatures. ok markus@
- Upstream-ID: ac8a048d24dcd89594b0052ea5e3404b473bfa2f
-
-commit 738c73dca2c99ee78c531b4cbeefc2008fe438f0
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 14 14:26:36 2017 +1000
-
- make explicit_bzero/memset safe for sz=0
-
-commit 8433d51e067e0829f5521c0c646b6fd3fe17e732
-Author: Tim Rice <tim@multitalents.net>
-Date: Tue Jul 11 18:47:56 2017 -0700
-
- modified: configure.ac
- UnixWare needs BROKEN_TCGETATTR_ICANON like Solaris
- Analysis by Robbie Zhang
-
-commit ff3507aea9c7d30cd098e7801e156c68faff7cc7
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jul 7 11:21:27 2017 +1000
-
- typo
+ OpenBSD-Commit-ID: 35ae46864e1f5859831ec0d115ee5ea50953a906
-commit d79bceb9311a9c137d268f5bc481705db4151810
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jun 30 04:17:23 2017 +0000
+commit 966ef478339ad5e631fb684d2a8effe846ce3fd4
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Dec 18 23:14:34 2017 +0000
upstream commit
- Only call close once in confree(). ssh_packet_close will
- close the FD so only explicitly close non-SSH channels. bz#2734, from
- bagajjal at microsoft.com, ok djm@
+ log mismatched RSA signature types; ok markus@
- Upstream-ID: a81ce0c8b023527167739fccf1732b154718ab02
-
-commit 197dc9728f062e23ce374f44c95a2b5f9ffa4075
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Jun 29 15:40:25 2017 +1000
-
- Update link for my patches.
+ OpenBSD-Commit-ID: 381bddfcc1e297a42292222f3bcb5ac2b7ea2418
-commit a98339edbc1fc21342a390f345179a9c3031bef7
+commit 349ecd4da3a985359694a74635748009be6baca6
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 28 01:09:22 2017 +0000
+Date: Mon Dec 18 23:13:42 2017 +0000
upstream commit
- Allow ssh-keygen to use a key held in ssh-agent as a CA when
- signing certificates. bz#2377 ok markus
+ pass kex->hostkey_alg and kex->hostkey_nid from pre-auth
+ to post-auth unpriviledged child processes; ok markus@
- Upstream-ID: fb42e920b592edcbb5b50465739a867c09329c8f
+ OpenBSD-Commit-ID: 4a35bc7af0a5f8a232d1361f79f4ebc376137302
-commit c9cdef35524bd59007e17d5bd2502dade69e2dfb
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 06:35:24 2017 +0000
+commit c9e37a8725c083441dd34a8a53768aa45c3c53fe
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Mon Dec 18 17:28:54 2017 +0000
upstream commit
- regress test for ExposeAuthInfo
+ Add helper function for uri handing in scp where a
+ missing path simply means ".". Also fix exit code and add warnings when an
+ invalid uri is encountered. OK otto@
- Upstream-Regress-ID: 190e5b6866376f4061c411ab157ca4d4e7ae86fd
+ OpenBSD-Commit-ID: 47dcf872380586dabf7fcc6e7baf5f8ad508ae1a
-commit f17ee61cad25d210edab69d04ed447ad55fe80c1
+commit 04c7e28f83062dc42f2380d1bb3a6bf0190852c0
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 07:08:57 2017 +0000
+Date: Mon Dec 18 02:25:15 2017 +0000
upstream commit
- correct env var name
+ pass negotiated signing algorithm though to
+ sshkey_verify() and check that the negotiated algorithm matches the type in
+ the signature (only matters for RSA SHA1/SHA2 sigs). ok markus@
- Upstream-ID: 721e761c2b1d6a4dcf700179f16fd53a1dadb313
+ OpenBSD-Commit-ID: 735fb15bf4adc060d3bee9d047a4bcaaa81b1af9
-commit 40962198e3b132cecdb32e9350acd4294e6a1082
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Jun 24 06:57:04 2017 +0000
+commit 931c78dfd7fe30669681a59e536bbe66535f3ee9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Dec 18 02:22:29 2017 +0000
upstream commit
- spelling;
+ sshkey_sigtype() function to return the type of a
+ signature; ok markus@
- Upstream-ID: 606f933c8e2d0be902ea663946bc15e3eee40b25
+ OpenBSD-Commit-ID: d3772b065ad6eed97285589bfb544befed9032e8
-commit 33f86265d7e8a0e88d3a81745d746efbdd397370
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 06:38:11 2017 +0000
+commit 4cdc5956f2fcc9e9078938db833142dc07d8f523
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Thu Dec 14 21:07:39 2017 +0000
upstream commit
- don't pass pointer to struct sshcipher between privsep
- processes, just redo the lookup in each using the already-passed cipher name.
- bz#2704 based on patch from Brooks Davis; ok markus dtucker
+ Replace ED25519's private SHA-512 implementation with a
+ call to the regular digest code. This speeds up compilation considerably. ok
+ markus@
- Upstream-ID: 2eab434c09bdf549dafd7da3e32a0d2d540adbe0
+ OpenBSD-Commit-ID: fcce8c3bcfe7389462a28228f63c823e80ade41c
-commit 8f574959272ac7fe9239c4f5d10fd913f8920ab0
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 06:34:38 2017 +0000
+commit 012e5cb839faf76549e3b6101b192fe1a74d367e
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Tue Dec 12 15:06:12 2017 +0000
upstream commit
- refactor authentication logging
+ Create a persistent umac128.c source file: #define the
+ output size and the name of the entry points for UMAC-128 before including
+ umac.c. Idea from FreeBSD. ok dtucker@
- optionally record successful auth methods and public credentials
- used in a file accessible to user sessions
+ OpenBSD-Commit-ID: 463cfacfa07cb8060a4d4961e63dca307bf3f4b1
+
+commit b35addfb4cd3b5cdb56a2a489d38e940ada926c7
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Mon Dec 11 16:23:28 2017 +1100
+
+ Update .depend with empty config.h
+
+commit 2d96f28246938e0ca474a939d8ac82ecd0de27e3
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Mon Dec 11 16:21:55 2017 +1100
+
+ Ensure config.h is always in dependencies.
- feedback and ok markus@
+ Put an empty config.h into the dependency list to ensure that it's
+ always listed and consistent.
+
+commit ac4987a55ee5d4dcc8e87f7ae7c1f87be7257d71
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Sun Dec 10 19:37:57 2017 +0000
+
+ upstream commit
- Upstream-ID: 090b93036967015717b9a54fd0467875ae9d32fb
+ ssh/lib hasn't worked towards our code-sharing goals for
+ a quit while, perhaps it is too verbose? Change each */Makefile to
+ specifying exactly what sources that program requires, compiling it seperate.
+ Maybe we'll iterate by sorting those into seperatable chunks, splitting up
+ files which contain common code + server/client specific code, or whatnot.
+ But this isn't one step, or we'd have done it a long time ago.. ok dtucker
+ markus djm
+
+ OpenBSD-Commit-ID: 5317f294d63a876bfc861e19773b1575f96f027d
-commit e2004d4bb7eb01c663dd3a3e7eb224f1ccdc9bba
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Jun 24 06:28:50 2017 +0000
+commit 48c23a39a8f1069a57264dd826f6c90aa12778d5
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Dec 10 05:55:29 2017 +0000
upstream commit
- word fix;
+ Put remote client info back into the ClientAlive
+ connection termination message. Based in part on diff from lars.nooden at
+ gmail, ok djm
- Upstream-ID: 8539bdaf2366603a34a9b2f034527ca13bb795c5
+ OpenBSD-Commit-ID: 80a0f619a29bbf2f32eb5297a69978a0e05d0ee0
-commit 4540428cd0adf039bcf5a8a27f2d5cdf09191513
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 05:37:44 2017 +0000
+commit aabd75ec76575c1b17232e6526a644097cd798e5
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Fri Dec 8 03:45:52 2017 +0000
upstream commit
- switch sshconnect.c from (slightly abused) select() to
- poll(); ok deraadt@ a while back
+ time_t printing needs %lld and (long long) casts ok djm
- Upstream-ID: efc1937fc591bbe70ac9e9542bb984f354c8c175
+ OpenBSD-Commit-ID: 4a93bc2b0d42a39b8f8de8bb74d07ad2e5e83ef7
-commit 6f8ca3b92540fa1a9b91670edc98d15448e3d765
+commit fd4eeeec16537870bd40d04836c7906ec141c17d
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 05:35:05 2017 +0000
+Date: Fri Dec 8 02:14:33 2017 +0000
upstream commit
- use HostKeyAlias if specified instead of hostname for
- matching host certificate principal names; bz#2728; ok dtucker@
+ fix ordering in previous to ensure errno isn't clobbered
+ before logging.
- Upstream-ID: dc2e11c83ae9201bbe74872a0c895ae9725536dd
+ OpenBSD-Commit-ID: e260bc1e145a9690dcb0d5aa9460c7b96a0c8ab2
-commit 8904ffce057b80a7472955f1ec00d7d5c250076c
+commit 155072fdb0d938015df828836beb2f18a294ab8a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 24 05:24:11 2017 +0000
+Date: Fri Dec 8 02:13:02 2017 +0000
upstream commit
- no need to call log_init to reinitialise logged PID in
- child sessions, since we haven't called openlog() in log_init() since 1999;
- ok markus@
+ for some reason unix_listener() logged most errors twice
+ with each message containing only some of the useful information; merge these
- Upstream-ID: 0906e4002af5d83d3d544df75e1187c932a3cf2e
+ OpenBSD-Commit-ID: 1978a7594a9470c0dddcd719586066311b7c9a4a
-commit e238645d789cd7eb47541b66aea2a887ea122c9b
-Author: mestre@openbsd.org <mestre@openbsd.org>
-Date: Fri Jun 23 07:24:48 2017 +0000
+commit 79c0e1d29959304e5a49af1dbc58b144628c09f3
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Mon Dec 11 14:38:33 2017 +1100
- upstream commit
+ Add autogenerated dependency info to Makefile.
- When using the escape sequence &~ the code path is
- client_loop() -> client_simple_escape_filter() -> process_escapes() -> fork()
- and the pledge for this path lacks the proc promise and therefore aborts the
- process. The solution is to just add proc the promise to this specific
- pledge.
+ Adds a .depend file containing dependency information generated by
+ makedepend, which is appended to the generated Makefile by configure.
- Reported by Gregoire Jadi gjadi ! omecha.info
- Insight with tb@, OK jca@
+ You can regen the file with "make -f Makefile.in depend" if necessary,
+ but we'll be looking at some way to automatically keep this up to date.
- Upstream-ID: 63c05e30c28209519f476023b65b0b1b0387a05b
+ "no objection" djm@
-commit 5abbb31c4e7a6caa922cc1cbb14e87a77f9d19d3
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jun 23 03:30:42 2017 +0000
+commit f001de8fbf7f3faddddd8efd03df18e57601f7eb
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Mon Dec 11 13:42:51 2017 +1100
+
+ Fix pasto in ldns handling.
+
+ When ldns-config is not found, configure would check the wrong variable.
+ ok djm@
+
+commit c5bfe83f67cb64e71cf2fe0d1500f6904b0099ee
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Sat Dec 9 10:12:23 2017 +1100
+
+ Portable switched to git so s/CVS/git/.
+
+commit bb82e61a40a4ee52e4eb904caaee2c27b763ab5b
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Sat Dec 9 08:06:00 2017 +1100
+
+ Remove now-used check for perl.
+
+commit e0ce54c0b9ca3a9388f9c50f4fa6cc25c28a3240
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Dec 6 05:06:21 2017 +0000
upstream commit
- Import regenerated moduli.
+ don't accept junk after "yes" or "no" responses to
+ hostkey prompts. bz#2803 reported by Maksim Derbasov; ok dtucker@
- Upstream-ID: b25bf747544265b39af74fe0716dc8d9f5b63b95
+ OpenBSD-Commit-ID: e1b159fb2253be973ce25eb7a7be26e6f967717c
-commit 849c5468b6d9b4365784c5dd88e3f1fb568ba38f
+commit 609d96b3d58475a15b2eb6b3d463f2c5d8e510c0
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jun 23 03:25:53 2017 +0000
+Date: Tue Dec 5 23:59:47 2017 +0000
upstream commit
- Run the screen twice so we end up with more candidate
- groups. ok djm@
+ Replace atoi and strtol conversions for integer arguments
+ to config keywords with a checking wrapper around strtonum. This will
+ prevent and flag invalid and negative arguments to these keywords. ok djm@
- Upstream-ID: b92c93266d8234d493857bb822260dacf4366157
+ OpenBSD-Commit-ID: 99ae3981f3d608a219ccb8d2fff635ae52c17998
-commit 4626e39c7053c6486c1c8b708ec757e464623f5f
+commit 168ecec13f9d7cb80c07df3bf7d414f4e4165e84
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Jun 14 00:31:38 2017 +0000
+Date: Tue Dec 5 23:56:07 2017 +0000
upstream commit
- Add user@host prefix to client's "Permisison denied"
- messages, useful in particular when using "stacked" connections where it's
- not clear which host is denying. bz#2720, ok djm@ markus@
+ Add missing break for rdomain. Prevents spurious
+ "Deprecated option" warnings. ok djm@
- Upstream-ID: de88e1e9dcb050c98e85377482d1287a9fe0d2be
+ OpenBSD-Commit-ID: ba28a675d39bb04a974586241c3cba71a9c6099a
-commit c948030d54911b2d3cddb96a7a8e9269e15d11cd
+commit 927f8514ceffb1af380a5f63ab4d3f7709b1b198
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jun 13 12:13:59 2017 +0000
+Date: Tue Dec 5 01:30:19 2017 +0000
upstream commit
- Do not require that unknown EXT_INFO extension values not
- contain \0 characters. This would cause fatal connection errors if an
- implementation sent e.g. string-encoded sub-values inside a value.
-
- Reported by Denis Bider; ok markus@
+ include the addr:port in bind/listen failure messages
- Upstream-ID: 030e10fdc605563c040244c4b4f1d8ae75811a5c
+ OpenBSD-Commit-ID: fdadb69fe1b38692608809cf0376b71c2c28e58e
-commit 6026f48dfca78b713e4a7f681ffa42a0afe0929e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jun 13 11:22:15 2017 +0000
+commit a8c89499543e2d889629c4e5e8dcf47a655cf889
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Nov 29 05:49:54 2017 +0000
+
+ upstream commit
+
+ Import updated moduli.
+
+ OpenBSD-Commit-ID: 524d210f982af6007aa936ca7f4c977f4d32f38a
+
+commit 3dde09ab38c8e1cfc28252be473541a81bc57097
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Tue Nov 28 21:10:22 2017 +0000
upstream commit
- missing prototype.
+ Have sftp print a warning about shell cleanliness when
+ decoding the first packet fails, which is usually caused by shells polluting
+ stdout of non-interactive starups. bz#2800, ok markus@ deraadt@.
- Upstream-ID: f443d2be9910fd2165a0667956d03343c46f66c9
+ OpenBSD-Commit-ID: 88d6a9bf3470f9324b76ba1cbd53e50120f685b5
-commit bcd1485075aa72ba9418003f5cc27af2b049c51b
-Author: Damien Miller <djm@mindrot.org>
-Date: Sat Jun 10 23:41:25 2017 +1000
+commit 6c8a246437f612ada8541076be2414846d767319
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Dec 1 17:11:47 2017 +1100
- portability for sftp globbed ls sort by mtime
+ Replace mkinstalldirs with mkdir -p.
- Include replacement timespeccmp() for systems that lack it.
- Support time_t struct stat->st_mtime in addition to
- timespec stat->st_mtim, as well as unsorted fallback.
+ Check for MIKDIR_P and use it instead of mkinstalldirs. Should fix "mkdir:
+ cannot create directory:... File exists" during "make install".
+ Patch from eb at emlix.com.
-commit 072e172f1d302d2a2c6043ecbfb4004406717b96
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 10 06:36:46 2017 +0000
+commit 3058dd78d2e43ed0f82ad8eab8bb04b043a72023
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Dec 1 17:07:08 2017 +1100
- upstream commit
-
- print '?' instead of incorrect link count (that the
- protocol doesn't provide) for remote listings. bz#2710 ok dtucker@
+ Pull in newer install-sh from autoconf-2.69.
- Upstream-ID: c611f98a66302cea452ef10f13fff8cf0385242e
+ Suggested by eb at emlix.com
-commit 72be5b2f8e7dc37235e8c4b8d0bc7b5ee1301505
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Jun 10 06:33:34 2017 +0000
+commit 79226e5413c5b0fda3511351a8511ff457e306d8
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Dec 1 16:55:35 2017 +1100
- upstream commit
-
- implement sorting for globbed ls; bz#2649 ok dtucker@
+ Remove RSA1 host key generation.
- Upstream-ID: ed3110f351cc9703411bf847ba864041fb7216a8
+ SSH1 support is now gone, remove SSH1 key generation.
+ Patch from eb at emlix.com.
-commit 5b2f34a74aa6a524cd57e856b23e1b7b25007721
+commit 2937dd02c572a12f33d5c334d518f6cbe0b645eb
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 9 06:47:13 2017 +0000
+Date: Tue Nov 28 06:09:38 2017 +0000
upstream commit
- return failure rather than fatal() for more cases during
- mux negotiations. Causes the session to fall back to a non-mux connection if
- they occur. bz#2707 ok dtucker@
+ more whitespace errors
- Upstream-ID: d2a7892f464d434e1f615334a1c9d0cdb83b29ab
+ OpenBSD-Commit-ID: 5e11c125378327b648940b90145e0d98beb05abb
-commit 7f5637c4a67a49ef256cb4eedf14e8590ac30976
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 9 06:43:01 2017 +0000
+commit 7f257bf3fd3a759f31098960cbbd1453fafc4164
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Tue Nov 28 06:04:51 2017 +0000
upstream commit
- in description of public key authentication, mention that
- the server will send debug messages to the client for some error conditions
- after authentication has completed. bz#2709 ok dtucker
+ whitespace at EOL
- Upstream-ID: 750127dbd58c5a2672c2d28bc35fe221fcc8d1dd
+ OpenBSD-Commit-ID: 76d3965202b22d59c2784a8df3a8bfa5ee67b96a
-commit 2076e4adb986512ce8c415dd194fd4e52136c4b4
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 9 06:40:24 2017 +0000
+commit 5db6fbf1438b108e5df3e79a1b4de544373bc2d4
+Author: dtucker@openbsd.org@openbsd.org <dtucker@openbsd.org@openbsd.org>
+Date: Sat Nov 25 06:46:22 2017 +0000
upstream commit
- better translate libcrypto errors by looking deeper in
- the accursed error stack for codes that indicate the wrong passphrase was
- supplied for a PEM key. bz#2699 ok dtucker@
+ Add monotime_ts and monotime_tv that return monotonic
+ timespec and timeval respectively. Replace calls to gettimeofday() in packet
+ timing with monotime_tv so that the callers will work over a clock step.
+ Should prevent integer overflow during clock steps reported by wangle6 at
+ huawei.com. "I like" markus@
- Upstream-ID: 4da4286326d570f4f0489459bb71f6297e54b681
+ OpenBSD-Commit-ID: 74d684264814ff806f197948b87aa732cb1b0b8a
-commit ad0531614cbe8ec424af3c0fa90c34a8e1ebee4c
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jun 9 04:40:04 2017 +0000
+commit 2d638e986085bdf1a40310ed6e2307463db96ea0
+Author: dtucker@openbsd.org@openbsd.org <dtucker@openbsd.org@openbsd.org>
+Date: Sat Nov 25 05:58:47 2017 +0000
upstream commit
- Add comments referring to the relevant RFC sections for
- rekeying behaviour.
+ Remove get_current_time() and replace with calls to
+ monotime_double() which uses CLOCK_MONOTONIC and works over clock steps. "I
+ like" markus@
- Upstream-ID: 6fc8e82485757a27633f9175ad00468f49a07d40
+ OpenBSD-Commit-ID: 3ad2f7d2414e2cfcaef99877a7a5b0baf2242952
-commit ce9134260b9b1247e2385a1afed00c26112ba479
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Jun 9 14:43:47 2017 +1000
+commit ba460acae48a36ef749cb23068f968f4d5d90a24
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Nov 24 16:24:31 2017 +1100
- drop two more privileges in the Solaris sandbox
-
- Drop PRIV_DAX_ACCESS and PRIV_SYS_IB_INFO.
- Patch from huieying.lee AT oracle.com via bz#2723
+ Include string.h for explicit_bzero.
-commit e0f609c8a2ab940374689ab8c854199c3c285a76
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Jun 9 13:36:29 2017 +1000
+commit a65655fb1a12b77fb22f9e71559b9d73030ec8ff
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Nov 24 10:23:47 2017 +1100
- Wrap stdint.h include in #ifdef.
+ fix incorrect range of OpenSSL versions supported
+
+ Pointed out by Solar Designer
-commit 1de5e47a85850526a4fdaf77185134046c050f75
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jun 7 01:48:15 2017 +0000
+commit 83a1e5dbec52d05775174f368e0c44b08619a308
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Wed Nov 15 02:10:16 2017 +0000
upstream commit
- unbreak after sshv1 purge
+ downgrade a couple more request parsing errors from
+ process-fatal to just returning failure, making them consistent with the
+ others that were already like that.
- Upstream-Regress-ID: 8ea01a92d5f571b9fba88c1463a4254a7552d51b
+ OpenBSD-Commit-ID: c111461f7a626690a2d53018ef26557b34652918
-commit 550c053168123fcc0791f9952abad684704b5760
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Jun 6 09:12:17 2017 +0000
+commit 93c68a8f3da8e5e6acdc3396f54d73919165e242
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Wed Nov 15 00:13:40 2017 +0000
upstream commit
- Fix compression output stats broken in rev 1.201. Patch
- originally by Russell Coker via Debian bug #797964 and Christoph Biedl. ok
- djm@
+ fix regression in 7.6: failure to parse a signature request
+ message shouldn't be fatal to the process, just the request. Reported by Ron
+ Frederick
- Upstream-ID: 83a1903b95ec2e4ed100703debb4b4a313b01016
+ OpenBSD-Commit-ID: e5d01b3819caa1a2ad51fc57d6ded43f48bbcc05
-commit 55d06c6e72a9abf1c06a7ac2749ba733134a1f39
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jun 2 06:06:10 2017 +0000
+commit 548d3a66feb64c405733932a6b1abeaf7198fa71
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Tue Nov 14 00:45:29 2017 +0000
upstream commit
- rationalise the long list of manual CDIAGFLAGS that we
- add; most of these were redundant to -Wall -Wextra
+ fix problem in configuration parsing when in config dump mode
+ (sshd -T) without providing a full connection specification (sshd -T -C ...)
- Upstream-ID: ea80f445e819719ccdcb237022cacfac990fdc5c
+ spotted by bluhm@
+
+ OpenBSD-Commit-ID: 7125faf5740eaa9d3a2f25400a0bc85e94e28b8f
-commit 1527d9f61e6d50f6c2b4a3fa5b45829034b1b0b1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 1 06:59:21 2017 +0000
+commit 33edb6ebdc2f81ebed1bceadacdfb8910b64fb88
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Nov 3 05:18:44 2017 +0000
upstream commit
- no need to bzero allocated space now that we use use
- recallocarray; ok deraadt@
+ reuse parse_multistate for parse_flag (yes/no arguments).
+ Saves a few lines of code and makes the parser more consistent wrt case-
+ sensitivity. bz#2664 ok dtucker@
- Upstream-ID: 53333c62ccf97de60b8cb570608c1ba5ca5803c8
+ OpenBSD-Commit-ID: b2ad1b6086858d5db71c7b11e5a74dba6d60efef
-commit cc812baf39b93d5355565da98648d8c31f955990
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 1 06:58:25 2017 +0000
+commit d52131a98316e76c0caa348f09bf6f7b9b01a1b9
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Nov 3 05:14:04 2017 +0000
upstream commit
- unconditionally zero init size of buffer; ok markus@
- deraadt@
+ allow certificate validity intervals that specify only a
+ start or stop time (we already support specifying both or neither)
- Upstream-ID: 218963e846d8f26763ba25afe79294547b99da29
+ OpenBSD-Commit-ID: 9be486545603c003030bdb5c467d1318b46b4e42
-commit 65eb8fae0d7ba45ef4483a3cf0ae7fd0dbc7c226
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jun 1 16:25:09 2017 +1000
+commit fbe8e7ac94c2fa380421a9205a8bc966549c2f91
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Nov 3 03:46:52 2017 +0000
- avoid compiler warning
+ upstream commit
+
+ allow "cd" and "lcd" commands with no explicit path
+ argument. lcd will change to the local user's home directory as usual. cd
+ will change to the starting directory for session (because the protocol
+ offers no way to obtain the remote user's home directory). bz#2760 ok
+ dtucker@
+
+ OpenBSD-Commit-ID: 15333f5087cee8c1ed1330cac1bd0a3e6a767393
-commit 2d75d74272dc2a0521fce13cfe6388800c9a2406
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 1 06:16:43 2017 +0000
+commit 0208a48517b5e8e8b091f32fa4addcd67c31ca9e
+Author: dtucker@openbsd.org@openbsd.org <dtucker@openbsd.org@openbsd.org>
+Date: Fri Nov 3 03:18:53 2017 +0000
upstream commit
- some warnings spotted by clang; ok markus@
+ When doing a config test with sshd -T, only require the
+ attributes that are actually used in Match criteria rather than (an
+ incomplete list of) all criteria. ok djm@, man page help jmc@
- Upstream-ID: 24381d68ca249c5cee4388ceb0f383fa5b43991b
+ OpenBSD-Commit-ID: b4e773c4212d3dea486d0259ae977551aab2c1fc
-commit 151c6e433a5f5af761c78de87d7b5d30a453cf5e
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jun 1 15:25:13 2017 +1000
+commit c357eed5a52cd2f4ff358b17e30e3f9a800644da
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Nov 3 02:32:19 2017 +0000
- add recallocarray replacement and dependency
+ upstream commit
- recallocarray() needs getpagesize() so add a tiny replacement for that.
+ typos in ECDSA certificate names; bz#2787 reported by
+ Mike Gerow
+
+ OpenBSD-Commit-ID: 824938b6aba1b31321324ba1f56c05f84834b163
-commit 01e6f78924da308447e71e9a32c8a6104ef4e888
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Jun 1 15:16:24 2017 +1000
+commit ecbf005b8fd80b81d0c61dfc1e96fe3da6099395
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Nov 3 02:29:17 2017 +0000
- add *.0 manpage droppings
+ upstream commit
+
+ Private keys in PEM format have been encrypted by AES-128 for
+ a while (not 3DES). bz#2788 reported by Calum Mackay
+
+ OpenBSD-Commit-ID: bd33da7acbbb3c882f0a0ee56007a35ce0d8a11a
-commit 4b2e2d3fd9dccff357e1e26ce9a5f2e103837a36
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu Jun 1 04:51:58 2017 +0000
+commit 81c9ccdbf6ddbf9bfbd6f1f775a5a7c13e47e185
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Nov 3 14:52:51 2017 +1100
- upstream commit
+ Check for linux/if.h when enabling rdomain.
- fix casts re constness
+ musl libc doesn't seem to have linux/if.h, so check for its presence
+ before enabling rdomain support on Linux.
+
+commit fa1b834cce41a1ce3e6a8d57fb67ef18c9dd803f
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Nov 3 14:09:45 2017 +1100
+
+ Add headers for sys/sysctl.h and net/route.h
- Upstream-ID: e38f2bac162b37dbaf784d349c8327a6626fa266
+ On at least older OpenBSDs, sys/sysctl.h and net/route.h require
+ sys/types and, in the case of sys/sysctl.h, sys/param.h for MAXLOGNAME.
-commit 75b8af8de805c0694b37fcf80ce82783b2acc86f
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed May 31 10:54:00 2017 +0000
+commit 41bff4da21fcd8a7c6a83a7e0f92b018f904f6fb
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Nov 3 02:22:41 2017 +0000
upstream commit
- make sure we don't pass a NULL string to vfprintf
- (triggered by the principals-command regress test); ok bluhm
+ avoid unused variable warnings for !WITH_OPENSSL; patch from
+ Marcus Folkesson
- Upstream-ID: eb49854f274ab37a0b57056a6af379a0b7111990
+ OpenBSD-Commit-ID: c01d27a3f907acdc3dd4ea48170fac3ba236d229
-commit 84008608c9ee944d9f72f5100f31ccff743b10f2
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed May 31 10:04:29 2017 +0000
+commit 6b373e4635a7470baa94253dd1dc8953663da9e8
+Author: Marcus Folkesson <marcus.folkesson@gmail.com>
+Date: Sat Oct 28 19:48:39 2017 +0200
- upstream commit
-
- use SO_ZEROIZE for privsep communication (if available)
+ only enable functions in dh.c when openssl is used
- Upstream-ID: abcbb6d2f8039fc4367a6a78096e5d5c39de4a62
+ Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
-commit 9e509d4ec97cb3d71696f1a2f1fdad254cbbce11
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed May 31 09:15:42 2017 +0000
+commit 939b30ba23848b572e15bf92f0f1a3d9cf3acc2b
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Wed Nov 1 00:04:15 2017 +0000
upstream commit
- Switch to recallocarray() for a few operations. Both
- growth and shrinkage are handled safely, and there also is no need for
- preallocation dances. Future changes in this area will be less error prone.
- Review and one bug found by markus
+ fix broken stdout in ControlPersist mode, introduced by me in
+ r1.467 and reported by Alf Schlichting
- Upstream-ID: 822d664d6a5a1d10eccb23acdd53578a679d5065
+ OpenBSD-Commit-ID: 3750a16e02108fc25f747e4ebcedb7123c1ef509
-commit dc5dc45662773c0f7745c29cf77ae2d52723e55e
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed May 31 08:58:52 2017 +0000
+commit f21455a084f9cc3942cf1bde64055a4916849fed
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Tue Oct 31 10:09:33 2017 +1100
- upstream commit
+ Include includes.h for HAVE_GETPAGESIZE.
- These shutdown() SHUT_RDWR are not needed before close()
- ok djm markus claudio
+ The configure script checks for getpagesize() and sets HAVE_GETPAGESIZE in
+ config.h, but bsd-getpagesize.c forgot to include includes.h (which
+ indirectly includes config.h) so the checks always fails, causing linker
+ issues when linking statically on systems with getpagesize().
- Upstream-ID: 36f13ae4ba10f5618cb9347933101eb4a98dbcb5
+ Patch from Peter Korsgaard <peter at korsgaard.com>
-commit 1e0cdf8efb745d0d1116e1aa22bdc99ee731695e
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed May 31 08:09:45 2017 +0000
+commit f2ad63c0718b93ac1d1e85f53fee33b06eef86b5
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Mon Oct 30 22:01:52 2017 +0000
upstream commit
- clear session keys from memory; ok djm@
+ whitespace at EOL
- Upstream-ID: ecd178819868975affd5fd6637458b7c712b6a0f
+ OpenBSD-Regress-ID: f4b5df99b28c6f63478deb916c6ed0e794685f07
-commit 92e9fe633130376a95dd533df6e5e6a578c1e6b8
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed May 31 07:00:13 2017 +0000
+commit c6415b1f8f1d0c2735564371647fd6a177fb9a3e
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Mon Oct 30 21:59:43 2017 +0000
upstream commit
- remove now obsolete ctx from ssh_dispatch_run; ok djm@
+ whitespace at EOL
- Upstream-ID: 9870aabf7f4d71660c31fda91b942b19a8e68d29
+ OpenBSD-Regress-ID: 19b1394393deee4c8a2114a3b7d18189f27a15cd
-commit 17ad5b346043c5bbc5befa864d0dbeb76be39390
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed May 31 05:34:14 2017 +0000
+commit e4d4ddbbba0e585ca3ec3a455430750b4622a6d3
+Author: millert@openbsd.org@openbsd.org <millert@openbsd.org@openbsd.org>
+Date: Wed Oct 25 20:08:36 2017 +0000
upstream commit
- use the ssh_dispatch_run_fatal variant
+ Use printenv to test whether an SSH_USER_AUTH is set
+ instead of using $SSH_USER_AUTH. The latter won't work with csh which treats
+ unknown variables as an error when expanding them. OK markus@
- Upstream-ID: 28c5b364e37c755d1b22652b8cd6735a05c625d8
+ OpenBSD-Regress-ID: f601e878dd8b71aa40381573dde3a8f567e6f2d1
-commit 39896b777320a6574dd06707aebac5fb98e666da
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed May 31 05:08:46 2017 +0000
+commit 116b1b439413a724ebb3320633a64dd0f3ee1fe7
+Author: millert@openbsd.org@openbsd.org <millert@openbsd.org@openbsd.org>
+Date: Tue Oct 24 19:33:32 2017 +0000
upstream commit
- another ctx => ssh conversion (in GSSAPI code)
-
- Upstream-ID: 4d6574c3948075c60608d8e045af42fe5b5d8ae0
-
-commit 6116bd4ed354a71a733c8fd0f0467ce612f12911
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed May 31 14:56:07 2017 +1000
-
- fix conversion of kexc25519s.c to struct ssh too
+ Add tests for URI parsing. OK markus@
- git cvsimport missed this commit for some reason
+ OpenBSD-Regress-ID: 5d1df19874f3b916d1a2256a905526e17a98bd3b
-commit d40dbdc85b6fb2fd78485ba02225511b8cbf20d7
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed May 31 04:29:44 2017 +0000
+commit dbe0662e9cd482593a4a8bf58c6481bfe8a747a4
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Oct 27 01:57:06 2017 +0000
upstream commit
- spell out that custom options/extensions should follow the
- usual SSH naming rules, e.g. "extension@example.com"
+ whitespace at EOL
- Upstream-ID: ab326666d2fad40769ec96b5a6de4015ffd97b8d
+ OpenBSD-Commit-ID: c95549cf5a07d56ea11aaff818415118720214f6
-commit 2a108277f976e8d0955c8b29d1dfde04dcbb3d5b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed May 31 04:17:12 2017 +0000
+commit d2135474344335a7c6ee643b6ade6db400fa76ee
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Oct 27 01:01:17 2017 +0000
upstream commit
- one more void *ctx => struct ssh *ssh conversion
+ whitespace at EOL (lots)
- Upstream-ID: d299d043471c10214cf52c03daa10f1c232759e2
+ OpenBSD-Commit-ID: 757257dd44116794ee1b5a45c6724973de181747
-commit c04e979503e97f52b750d3b98caa6fe004ab2ab9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed May 31 00:43:04 2017 +0000
+commit b77c29a07f5a02c7c1998701c73d92bde7ae1608
+Author: djm@openbsd.org@openbsd.org <djm@openbsd.org@openbsd.org>
+Date: Fri Oct 27 00:18:41 2017 +0000
upstream commit
- fix possible OOB strlen() in SOCKS4A hostname parsing;
- ok markus@
+ improve printing of rdomain on accept() a little
- Upstream-ID: c67297cbeb0e5a19d81752aa18ec44d31270cd11
+ OpenBSD-Commit-ID: 5da58db2243606899cedaa646c70201b2d12247a
-commit a3bb250c93bfe556838c46ed965066afce61cffa
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 30 19:38:17 2017 +0000
+commit 68d3bbb2e6dfbf117c46e942142795b2cdd0274b
+Author: jmc@openbsd.org@openbsd.org <jmc@openbsd.org@openbsd.org>
+Date: Thu Oct 26 06:44:01 2017 +0000
upstream commit
- tweak previous;
+ mark up the rdomain keyword;
- Upstream-ID: 66987651046c42d142f7318c9695fb81a6d14031
+ OpenBSD-Commit-ID: 1b597d0ad0ad20e94dbd61ca066057e6f6313b8a
-commit 1112b534a6a7a07190e497e6bf86b0d5c5fb02dc
-Author: bluhm@openbsd.org <bluhm@openbsd.org>
-Date: Tue May 30 18:58:37 2017 +0000
+commit 0b2e2896b9d0d6cfb59e9ec8271085296bd4e99b
+Author: jmc@openbsd.org@openbsd.org <jmc@openbsd.org@openbsd.org>
+Date: Wed Oct 25 06:19:46 2017 +0000
upstream commit
- Add RemoteCommand option to specify a command in the
- ssh config file instead of giving it on the client's command line. This
- command will be executed on the remote host. The feature allows to automate
- tasks using ssh config. OK markus@
+ tweak the uri text, specifically removing some markup to
+ make it a bit more readable;
- Upstream-ID: 5d982fc17adea373a9c68cae1021ce0a0904a5ee
+ issue reported by - and diff ok - millert
+
+ OpenBSD-Commit-ID: 8b56a20208040b2d0633536fd926e992de37ef3f
-commit eb272ea4099fd6157846f15c129ac5727933aa69
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:29:59 2017 +0000
+commit 7530e77bdc9415386d2a8ea3d086e8b611b2ba40
+Author: jmc@openbsd.org@openbsd.org <jmc@openbsd.org@openbsd.org>
+Date: Wed Oct 25 06:18:06 2017 +0000
upstream commit
- switch auth2 to ssh_dispatch API; ok djm@
+ simplify macros in previous, and some minor tweaks;
- Upstream-ID: a752ca19e2782900dd83060b5c6344008106215f
+ OpenBSD-Commit-ID: 6efeca3d8b095b76e21b484607d9cc67ac9a11ca
-commit 5a146bbd4fdf5c571f9fb438e5210d28cead76d9
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:27:22 2017 +0000
+commit eb9c582b710dc48976b48eb2204218f6863bae9a
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Oct 31 00:46:29 2017 +1100
- upstream commit
+ Switch upstream git repository.
- switch auth2-none.c to modern APIs; ok djm@
+ Previously portable OpenSSH has synced against a conversion of OpenBSD's
+ CVS repository made using the git cvsimport tool, but this has become
+ increasingly unreliable.
- Upstream-ID: 07252b58e064d332214bcabbeae8e08c44b2001b
-
-commit 60306b2d2f029f91927c6aa7c8e08068519a0fa2
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:26:49 2017 +0000
-
- upstream commit
+ As of this commit, portable OpenSSH now tracks a conversion of the
+ OpenBSD CVS upstream made using the excellent cvs2gitdump tool from
+ YASUOKA Masahiko: https://github.com/yasuoka/cvs2gitdump
- switch auth2-passwd.c to modern APIs; ok djm@
+ cvs2gitdump is considerably more reliable than gitcvsimport and the old
+ version of cvsps that it uses under the hood, and is the same tool used
+ to export the entire OpenBSD repository to git (so we know it can cope
+ with future growth).
- Upstream-ID: cba0a8b72b4f97adfb7e3b3fd2f8ba3159981fc7
-
-commit eb76698b91338bd798c978d4db2d6af624d185e4
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:25:42 2017 +0000
-
- upstream commit
+ These new conversions are mirrored at github, so interested parties can
+ match portable OpenSSH commits to their upstream counterparts.
- switch auth2-hostbased.c to modern APIs; ok djm@
+ https://github.com/djmdjm/openbsd-openssh-src
+ https://github.com/djmdjm/openbsd-openssh-regress
- Upstream-ID: 146af25c36daeeb83d5dbbb8ca52b5d25de88f4e
-
-commit 2ae666a8fc20b3b871b2f1b90ad65cc027336ccd
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:23:52 2017 +0000
-
- upstream commit
+ An unfortunate side effect of switching upstreams is that we must have
+ a flag day, across which the upstream commit IDs will be inconsistent.
+ The old commit IDs are recorded with the tags "Upstream-ID" for main
+ directory commits and "Upstream-Regress-ID" for regress commits.
- protocol handlers all get struct ssh passed; ok djm@
+ To make it clear that the commit IDs do not refer to the same
+ things, the new repository will instead use "OpenBSD-ID" and
+ "OpenBSD-Regress-ID" tags instead.
- Upstream-ID: 0ca9ea2a5d01a6d2ded94c5024456a930c5bfb5d
+ Apart from being a longwinded explanation of what is going on, this
+ commit message also serves to synchronise our tools with the state of
+ the tree, which happens to be:
+
+ OpenBSD-ID: 9c43a9968c7929613284ea18e9fb92e4e2a8e4c1
+ OpenBSD-Regress-ID: b33b385719420bf3bc57d664feda6f699c147fef
-commit 94583beb24a6c5fd19cedb9104ab2d2d5cd052b6
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:19:15 2017 +0000
+commit 2de5c6b53bf063ac698596ef4e23d8e3099656ea
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Oct 27 08:42:33 2017 +1100
+
+ fix rdomain compilation errors
+
+commit 6bd5b569fd6dfd5e8c8af20bbc41e45c2d6462ab
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 14:15:42 2017 +1100
+
+ autoconf glue to enable Linux VRF
+
+commit 97c5aaf925d61641d599071abb56012cde265978
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 14:09:56 2017 +1100
- upstream commit
-
- ssh: pass struct ssh to auth functions, too; ok djm@
-
- Upstream-ID: d13c509cc782f8f19728fbea47ac7cf36f6e85dd
+ basic valid_rdomain() implementation for Linux
-commit 5f4082d886c6173b9e90b9768c9a38a3bfd92c2b
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:18:15 2017 +0000
+commit ce1cca39d7935dd394080ce2df62f5ce5b51f485
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 13:47:59 2017 +1100
- upstream commit
-
- sshd: pass struct ssh to auth functions; ok djm@
+ implement get/set_rdomain() for Linux
- Upstream-ID: b00a80c3460884ebcdd14ef550154c761aebe488
+ Not enabled, pending implementation of valid_rdomain() and autoconf glue
-commit 7da5df11ac788bc1133d8d598d298e33500524cc
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:16:41 2017 +0000
+commit 6eee79f9b8d4a3b113b698383948a119acb82415
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 13:22:29 2017 +1100
- upstream commit
-
- remove unused wrapper functions from key.[ch]; ok djm@
-
- Upstream-ID: ea0f4016666a6817fc11f439dd4be06bab69707e
+ stubs for rdomain replacement functions
-commit ff7371afd08ac0bbd957d90451d4dcd0da087ef5
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:15:17 2017 +0000
+commit f5594f939f844bbb688313697d6676238da355b3
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 13:13:57 2017 +1100
- upstream commit
-
- sshkey_new() might return NULL (pkcs#11 code only); ok
- djm@
+ rename port-tun.[ch] => port-net.[ch]
- Upstream-ID: de9f2ad4a42c0b430caaa7d08dea7bac943075dd
+ Ahead of adding rdomain support
-commit beb965bbc5a984fa69fb1e2b45ebe766ae09d1ef
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:13:40 2017 +0000
+commit d685e5a31feea35fb99e1a31a70b3c60a7f2a0eb
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 25 02:10:39 2017 +0000
upstream commit
- switch sshconnect.c to modern APIs; ok djm@
+ uninitialised variable in PermitTunnel printing code
- Upstream-ID: 27be17f84b950d5e139b7a9b281aa487187945ad
+ Upstream-ID: f04dc33e42855704e116b8da61095ecc71bc9e9a
-commit 00ed75c92d1f95fe50032835106c368fa22f0f02
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 14:10:53 2017 +0000
+commit 43c29bb7cfd46bbbc61e0ffa61a11e74d49a712f
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 13:10:59 2017 +1100
- upstream commit
-
- switch auth2-pubkey.c to modern APIs; with & ok djm@
-
- Upstream-ID: 8f08d4316eb1b0c4ffe4a206c05cdd45ed1daf07
+ provide hooks and fallbacks for rdomain support
-commit 54d90ace1d3535b44d92a8611952dc109a74a031
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 08:52:19 2017 +0000
+commit 3235473bc8e075fad7216b7cd62fcd2b0320ea04
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Oct 25 11:25:43 2017 +1100
- upstream commit
-
- switch from Key typedef with struct sshkey; ok djm@
-
- Upstream-ID: 3067d33e04efbe5131ce8f70668c47a58e5b7a1f
+ check for net/route.h and sys/sysctl.h
-commit c221219b1fbee47028dcaf66613f4f8d6b7640e9
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 08:49:58 2017 +0000
+commit 4d5456c7de108e17603a0920c4d15bca87244921
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 25 00:21:37 2017 +0000
upstream commit
- remove ssh1 references; ok djm@
+ transfer ownership of stdout to the session channel by
+ dup2'ing /dev/null to fd 1. This allows propagation of remote stdout close to
+ the local side; reported by David Newall, ok markus@
- Upstream-ID: fc23b7578e7b0a8daaec72946d7f5e58ffff5a3d
+ Upstream-ID: 8d9ac18a11d89e6b0415f0cbf67b928ac67f0e79
-commit afbfa68fa18081ef05a9cd294958509a5d3cda8b
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Tue May 30 08:49:32 2017 +0000
+commit 68af80e6fdeaeb79432209db614386ff0f37e75f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 25 00:19:47 2017 +0000
upstream commit
- revise sshkey_load_public(): remove ssh1 related
- comments, remove extra open()/close() on keyfile, prevent leak of 'pub' if
- 'keyp' is NULL, replace strlcpy+cat with asprintf; ok djm@
+ add a "rdomain" criteria for the sshd_config Match
+ keyword to allow conditional configuration that depends on which rdomain(4) a
+ connection was recevied on. ok markus@
- Upstream-ID: 6175e47cab5b4794dcd99c1175549a483ec673ca
+ Upstream-ID: 27d8fd5a3f1bae18c9c6e533afdf99bff887a4fb
-commit 813f55336a24fdfc45e7ed655fccc7d792e8f859
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Fri May 26 20:34:49 2017 +0000
+commit 35eb33fb957979e3fcbe6ea0eaee8bf4a217421a
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 25 00:17:08 2017 +0000
upstream commit
- sshbuf_consume: reset empty buffer; ok djm@
+ add sshd_config RDomain keyword to place sshd and the
+ subsequent user session (including the shell and any TCP/IP forwardings) into
+ the specified rdomain(4)
- Upstream-ID: 0d4583ba57f69e369d38bbd7843d85cac37fa821
+ ok markus@
+
+ Upstream-ID: be2358e86346b5cacf20d90f59f980b87d1af0f5
-commit 6cf711752cc2a7ffaad1fb4de18cae65715ed8bb
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Fri May 26 19:35:50 2017 +0000
+commit acf559e1cffbd1d6167cc1742729fc381069f06b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 25 00:15:35 2017 +0000
upstream commit
- remove SSH_CHANNEL_XXX_DRAINING (ssh1 only); ok djm@
+ Add optional rdomain qualifier to sshd_config's
+ ListenAddress option to allow listening on a different rdomain(4), e.g.
- Upstream-ID: e2e225b6ac67b84dd024f38819afff2554fafe42
+ ListenAddress 0.0.0.0 rdomain 4
+
+ Upstream-ID: 24b6622c376feeed9e9be8b9605e593695ac9091
-commit 364f0d5edea27767fb0f915ea7fc61aded88d3e8
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Fri May 26 19:34:12 2017 +0000
+commit b9903ee8ee8671b447fc260c2bee3761e26c7227
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Tue Oct 24 19:41:45 2017 +0000
upstream commit
- remove channel_input_close_confirmation (ssh1 only); ok
- djm@
+ Kill dead store and some spaces vs. tabs indent in
+ parse_user_host_path(). Noticed by markus@
- Upstream-ID: 8e7c8c38f322d255bb0294a5c0ebef53fdf576f1
+ Upstream-ID: 114fec91dadf9af46c7c94fd40fc630ea2de8200
-commit 8ba0fd40082751dbbc23a830433488bbfb1abdca
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri May 26 01:40:07 2017 +0000
+commit 0869627e00f4ee2a038cb62d7bd9ffad405e1800
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue Oct 24 06:27:42 2017 +0000
upstream commit
- fix references to obsolete v00 cert format; spotted by
- Jakub Jelen
+ tweak previous; ok djm
- Upstream-ID: 7600ce193ab8fd19451acfe24fc2eb39d46b2c4f
+ Upstream-ID: 7d913981ab315296be1f759c67b6e17aea38fca9
-commit dcc714c65cfb81eb6903095b4590719e8690f3da
-Author: Mike Frysinger <vapier@chromium.org>
-Date: Wed May 24 23:21:19 2017 -0400
+commit e3fa20e2e58fdc88a0e842358778f2de448b771b
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon Oct 23 16:25:24 2017 +1100
- configure: actually set cache vars when cross-compiling
-
- The cross-compiling fallback message says it's assuming the test
- passed, but it didn't actually set the cache var which causes
- later tests to fail.
+ avoid -Wsign-compare warning in argv copying
-commit 947a3e829a5b8832a4768fd764283709a4ca7955
+commit b7548b12a6b2b4abf4d057192c353147e0abba08
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat May 20 02:35:47 2017 +0000
+Date: Mon Oct 23 05:08:00 2017 +0000
upstream commit
- there's no reason to artificially limit the key path
- here, just check that it fits PATH_MAX; spotted by Matthew Patton
+ Expose devices allocated for tun/tap forwarding.
- Upstream-ID: 858addaf2009c9cf04d80164a41b2088edb30b58
+ At the client, the device may be obtained from a new %T expansion
+ for LocalCommand.
+
+ At the server, the allocated devices will be listed in a
+ SSH_TUNNEL variable exposed to the environment of any user sessions
+ started after the tunnel forwarding was established.
+
+ ok markus
+
+ Upstream-ID: e61e53f8ae80566e9ddc0d67a5df5bdf2f3c9f9e
-commit 773224802d7cb250bb8b461546fcce10567b4b2e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri May 19 21:07:17 2017 +0000
+commit 887669ef032d63cf07f53cada216fa8a0c9a7d72
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Sat Oct 21 23:06:24 2017 +0000
upstream commit
- Now that we no longer support SSHv1, replace the contents
- of this file with a pointer to
- https://tools.ietf.org/html/draft-miller-ssh-agent-00 It's better edited,
- doesn't need to document stuff we no longer implement and does document stuff
- that we do implement (RSA SHA256/512 signature flags)
+ Add URI support to ssh, sftp and scp. For example
+ ssh://user@host or sftp://user@host/path. The connection parameters
+ described in draft-ietf-secsh-scp-sftp-ssh-uri-04 are not implemented since
+ the ssh fingerprint format in the draft uses md5 with no way to specify the
+ hash function type. OK djm@
- Upstream-ID: da8cdc46bbcc266efabd565ddddd0d8e556f846e
+ Upstream-ID: 4ba3768b662d6722de59e6ecb00abf2d4bf9cacc
-commit 54cd41a4663fad66406dd3c8fe0e4760ccd8a899
+commit d27bff293cfeb2252f4c7a58babe5ad3262c6c98
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Oct 20 13:22:00 2017 +1100
+
+ Fix missed RCSID merges
+
+commit d3b6aeb546242c9e61721225ac4387d416dd3d5e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed May 17 01:24:17 2017 +0000
+Date: Fri Oct 20 02:13:41 2017 +0000
upstream commit
- allow LogLevel in sshd_config Match blocks; ok dtucker
- bz#2717
+ more RCSIDs
- Upstream-ID: 662e303be63148f47db1aa78ab81c5c2e732baa8
+ Upstream-Regress-ID: 1aecbe3f8224793f0ec56741a86d619830eb33be
-commit 277abcda3f1b08d2376686f0ef20320160d4c8ab
+commit b011edbb32e41aaab01386ce4c0efcc9ff681c4a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue May 16 16:56:15 2017 +0000
+Date: Fri Oct 20 01:56:39 2017 +0000
upstream commit
- remove duplicate check; spotted by Jakub Jelen
+ add RCSIDs to these; they make syncing portable a bit
+ easier
- Upstream-ID: 30c2996c1767616a8fdc49d4cee088efac69c3b0
+ Upstream-ID: 56cb7021faea599736dd7e7f09c2e714425b1e68
-commit adb47ce839c977fa197e770c1be8f852508d65aa
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue May 16 16:54:05 2017 +0000
+commit 6eb27597781dccaf0ec2b80107a9f0592a0cb464
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Oct 20 12:54:15 2017 +1100
upstream commit
- mention that Ed25519 keys are valid as CA keys; spotted
- by Jakub Jelen
+ Apply missing commit 1.11 to kexc25519s.c
- Upstream-ID: d3f6db58b30418cb1c3058211b893a1ffed3dfd4
+ Upstream-ID: 5f020e23a1ee6c3597af1f91511e68552cdf15e8
-commit 6bdf70f01e700348bb4d8c064c31a0ab90896df6
+commit 6f72280553cb6918859ebcacc717f2d2fafc1a27
Author: Damien Miller <djm@mindrot.org>
-Date: Tue May 9 14:35:03 2017 +1000
+Date: Fri Oct 20 12:52:50 2017 +1100
- clean up regress files and add a .gitignore
+ upstream commit
+
+ Apply missing commit 1.127 to servconf.h
+
+ Upstream-ID: f14c4bac74a2b7cf1e3cff6bea5c447f192a7d15
-commit 7bdb2eeb1d3c26acdc409bd94532eefa252e440b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 8 22:57:38 2017 +0000
+commit bb3e16ab25cb911238c2eb7455f9cf490cb143cc
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Wed Oct 18 05:36:59 2017 +0000
upstream commit
- remove hmac-ripemd160; ok dtucker
+ remove unused Pp;
- Upstream-ID: 896e737ea0bad6e23327d1c127e02d5e9e9c654d
+ Upstream-ID: 8ad26467f1f6a40be887234085a8e01a61a00550
-commit 5f02bb1f99f70bb422be8a5c2b77ef853f1db554
+commit 05b69e99570553c8e1eafb895b1fbf1d098d2e14
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 8 06:11:06 2017 +0000
+Date: Wed Oct 18 02:49:44 2017 +0000
upstream commit
- make requesting bad ECDSA bits yield the same error
- (SSH_ERR_KEY_LENGTH) as the same mistake for RSA/DSA
+ In the description of pattern-lists, clarify negated
+ matches by explicitly stating that a negated match will never yield a
+ positive result, and that at least one positive term in the pattern-list must
+ match. bz#1918
- Upstream-ID: bf40d3fee567c271e33f05ef8e4e0fa0b6f0ece6
+ Upstream-ID: 652d2f9d993f158fc5f83cef4a95cd9d95ae6a14
-commit d757a4b633e8874629a1442c7c2e7b1b55d28c19
+commit eb80e26a15c10bc65fed8b8cdb476819a713c0fd
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 8 06:08:42 2017 +0000
+Date: Fri Oct 13 21:13:54 2017 +0000
upstream commit
- fix for new SSH_ERR_KEY_LENGTH error value
+ log debug messages sent to peer; ok deraadt markus
- Upstream-Regress-ID: c38a6e6174d4c3feca3518df150d4fbae0dca8dc
+ Upstream-ID: 3b4fdc0a06ea5083f61d96e20043000f477103d9
-commit 2e58a69508ac49c02d1bb6057300fa6a76db1045
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 8 06:03:39 2017 +0000
+commit 071325f458d615d7740da5c1c1d5a8b68a0b4605
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Oct 13 16:50:45 2017 +0000
upstream commit
- helps if I commit the correct version of the file. fix
- missing return statement.
+ trim permitrootlogin description somewhat, to avoid
+ ambiguity; original diff from walter alejandro iglesias, tweaked by sthen and
+ myself
- Upstream-ID: c86394a3beeb1ec6611e659bfa830254f325546c
+ ok sthen schwarze deraadt
+
+ Upstream-ID: 1749418b2bc073f3fdd25fe21f8263c3637fe5d2
-commit effaf526bfa57c0ac9056ca236becf52385ce8af
+commit 10727487becb897a15f658e0cb2d05466236e622
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 8 01:52:49 2017 +0000
+Date: Fri Oct 13 06:45:18 2017 +0000
upstream commit
- remove arcfour, blowfish and CAST here too
+ mention SSH_USER_AUTH in the list of environment
+ variables
- Upstream-Regress-ID: c613b3bcbef75df1fe84ca4dc2d3ef253dc5e920
+ Upstream-ID: 1083397c3ee54b4933121ab058c70a0fc6383691
-commit 7461a5bc571696273252df28a1f1578968cae506
+commit 224f193d6a4b57e7a0cb2b9ecd3b6c54d721d8c2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 8 00:21:36 2017 +0000
+Date: Fri Oct 13 06:24:51 2017 +0000
upstream commit
- I was too aggressive with the scalpel in the last commit;
- unbreak sshd, spotted quickly by naddy@
+ BIO_get_mem_data() is supposed to take a char* as pointer
+ argument, so don't pass it a const char*
- Upstream-ID: fb7e75d2b2c7e6ca57dee00ca645e322dd49adbf
+ Upstream-ID: 1ccd91eb7f4dd4f0fa812d4f956987cd00b5f6ec
-commit bd636f40911094a39c2920bf87d2ec340533c152
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun May 7 23:15:59 2017 +0000
+commit cfa46825b5ef7097373ed8e31b01a4538a8db565
+Author: benno@openbsd.org <benno@openbsd.org>
+Date: Mon Oct 9 20:12:51 2017 +0000
upstream commit
- Refuse RSA keys <1024 bits in length. Improve reporting
- for keys that do not meet this requirement. ok markus@
+ clarify the order in which config statements are used. ok
+ jmc@ djm@
- Upstream-ID: b385e2a7b13b1484792ee681daaf79e1e203df6c
+ Upstream-ID: e37e27bb6bbac71315e22cb9690fd8a556a501ed
-commit 70c1218fc45757a030285051eb4d209403f54785
+commit dceabc7ad7ebc7769c8214a1647af64c9a1d92e5
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun May 7 23:13:42 2017 +0000
+Date: Thu Oct 5 15:52:03 2017 +0000
upstream commit
- Don't offer CBC ciphers by default in the client. ok
- markus@
+ replace statically-sized arrays in ServerOptions with
+ dynamic ones managed by xrecallocarray, removing some arbitrary (though
+ large) limits and saving a bit of memory; "much nicer" markus@
- Upstream-ID: 94c9ce8d0d1a085052e11c7f3307950fdc0901ef
+ Upstream-ID: 1732720b2f478fe929d6687ac7b0a97ff2efe9d2
-commit acaf34fd823235d549c633c0146ee03ac5956e82
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun May 7 23:12:57 2017 +0000
+commit 2b4f3ab050c2aaf6977604dd037041372615178d
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Thu Oct 5 12:56:50 2017 +0000
upstream commit
- As promised in last release announcement: remove
- support for Blowfish, RC4 and CAST ciphers. ok markus@ deraadt@
+ %C is hashed; from klemens nanni ok markus
- Upstream-ID: 21f8facdba3fd8da248df6417000867cec6ba222
+ Upstream-ID: 6ebed7b2e1b6ee5402a67875d74f5e2859d8f998
-commit 3e371bd2124427403971db853fb2e36ce789b6fd
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Fri May 5 10:42:49 2017 +0000
+commit a66714508b86d6814e9055fefe362d9fe4d49ab3
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Oct 4 18:50:23 2017 +0000
upstream commit
- more simplification and removal of SSHv1-related code;
- ok djm@
+ exercise PermitOpen a little more thoroughly
- Upstream-ID: d2f041aa0b79c0ebd98c68a01e5a0bfab2cf3b55
+ Upstream-Regress-ID: f41592334e227a4c1f9a983044522de4502d5eac
-commit 2e9c324b3a7f15c092d118c2ac9490939f6228fd
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Fri May 5 10:41:58 2017 +0000
+commit 609ecc8e57eb88e2eac976bd3cae7f7889aaeff6
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Tue Sep 26 22:39:25 2017 +0000
upstream commit
- remove superfluous protocol 2 mentions; ok jmc@
+ UsePrivilegeSeparation is gone, stop trying to test it.
- Upstream-ID: 0aaf7567c9f2e50fac5906b6a500a39c33c4664d
+ Upstream-Regress-ID: 796a5057cfd79456a20ea935cc53f6eb80ace191
-commit 744bde79c3361e2153cb395a2ecdcee6c713585d
+commit 69bda0228861f3dacd4fb3d28b60ce9d103d254b
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu May 4 06:10:57 2017 +0000
+Date: Wed Oct 4 18:49:30 2017 +0000
upstream commit
- since a couple of people have asked, leave a comment
- explaining why we retain SSH v.1 support in the "delete all keys from agent"
- path.
+ fix (another) problem in PermitOpen introduced during the
+ channels.c refactor: the third and subsequent arguments to PermitOpen were
+ being silently ignored; ok markus@
- Upstream-ID: 4b42dcfa339813c15fe9248a2c1b7ed41c21bbb4
+ Upstream-ID: 067c89f1f53cbc381628012ba776d6861e6782fd
-commit 0c378ff6d98d80bc465a4a6a787670fb9cc701ee
+commit 66bf74a92131b7effe49fb0eefe5225151869dc5
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Thu May 4 01:33:21 2017 +0000
+Date: Mon Oct 2 19:33:20 2017 +0000
upstream commit
- another tentacle: cipher_set_key_string() was only ever
- used for SSHv1
+ Fix PermitOpen crash; spotted by benno@, ok dtucker@ deraadt@
- Upstream-ID: 7fd31eb6c48946f7e7cc12af0699fe8eb637e94a
+ Upstream-ID: c2cc84ffac070d2e1ff76182c70ca230a387983c
-commit 9a82e24b986e3e0dc70849dbb2c19aa6c707b37f
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Wed May 3 21:49:18 2017 +0000
+commit d63b38160a59039708fd952adc75a0b3da141560
+Author: Damien Miller <djm@mindrot.org>
+Date: Sun Oct 1 10:32:25 2017 +1100
- upstream commit
-
- restore mistakenly deleted description of the
- ConnectionAttempts option ok markus@
+ update URL again
- Upstream-ID: 943002b1b7c470caea3253ba7b7348c359de0348
+ I spotted a typo in the draft so uploaded a new version...
-commit 768405fddf64ff83aa6ef701ebb3c1f82d98a2f3
-Author: naddy@openbsd.org <naddy@openbsd.org>
-Date: Wed May 3 21:08:09 2017 +0000
+commit 6f64f596430cd3576c529f07acaaf2800aa17d58
+Author: Damien Miller <djm@mindrot.org>
+Date: Sun Oct 1 10:01:56 2017 +1100
+
+ sync release notes URL
+
+commit 35ff70a04dd71663a5ac1e73b90d16d270a06e0d
+Author: Damien Miller <djm@mindrot.org>
+Date: Sun Oct 1 10:01:25 2017 +1100
+
+ sync contrib/ssh-copy-id with upstream
+
+commit 290843b8ede85f8b30bf29cd7dceb805c3ea5b66
+Author: Damien Miller <djm@mindrot.org>
+Date: Sun Oct 1 09:59:19 2017 +1100
+
+ update version in RPM spec files
+
+commit 4e4e0bb223c5be88d87d5798c75cc6b0d4fef31d
+Author: Damien Miller <djm@mindrot.org>
+Date: Sun Oct 1 09:58:24 2017 +1100
+
+ update agent draft URL
+
+commit e4a798f001d2ecd8bf025c1d07658079f27cc604
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Sep 30 22:26:33 2017 +0000
upstream commit
- remove miscellaneous SSH1 leftovers; ok markus@
+ openssh-7.6; ok deraadt@
- Upstream-ID: af23696022ae4d45a1abc2fb8b490d8d9dd63b7c
+ Upstream-ID: a39c3a5b63a1baae109ae1ae4c7c34c2a59acde0
-commit 1a1b24f8229bf7a21f89df21987433283265527a
+commit 5fa1407e16e7e5fda9769d53b626ce39d5588d4d
Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Wed May 3 10:01:44 2017 +0000
+Date: Wed Sep 27 06:45:53 2017 +0000
upstream commit
- more protocol 1 bits removed; ok djm
+ tweak EposeAuthinfo; diff from lars nooden
- Upstream-ID: b5b977eaf756915acb56aef3604a650e27f7c2b9
+ tweaked by sthen; ok djm dtucker
+
+ Upstream-ID: 8f2ea5d2065184363e8be7a0ba24d98a3b259748
-commit 2b6f799e9b230cf13a7eefc05ecead7d8569d6b5
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Wed May 3 06:32:02 2017 +0000
+commit bba69c246f0331f657fd6ec97724df99fc1ad174
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Sep 28 16:06:21 2017 -0700
- upstream commit
+ don't fatal ./configure for LibreSSL
+
+commit 04dc070e8b4507d9d829f910b29be7e3b2414913
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Sep 28 14:54:34 2017 -0700
+
+ abort in configure when only openssl-1.1.x found
- more protocol 1 stuff to go; ok djm
+ We don't support openssl-1.1.x yet (see multiple threads on the
+ openssh-unix-dev@ mailing list for the reason), but previously
+ ./configure would accept it and the compilation would subsequently
+ fail. This makes ./configure display an explicit error message and
+ abort.
- Upstream-ID: 307a30441d2edda480fd1661d998d36665671e47
+ ok dtucker@
-commit f10c0d32cde2084d2a0b19bc47d80cb93e85a093
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 2 17:04:09 2017 +0000
+commit 74c1c3660acf996d9dc329e819179418dc115f2c
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Wed Sep 27 07:44:41 2017 +1000
+
+ Check for and handle calloc(p, 0) = NULL.
+
+ On some platforms (AIX, maybe others) allocating zero bytes of memory
+ via the various *alloc functions returns NULL, which is permitted
+ by the standards. Autoconf has some macros for detecting this (with
+ the exception of calloc for some reason) so use these and if necessary
+ activate shims for them. ok djm@
+
+commit 6a9481258a77b0b54b2a313d1761c87360c5f1f5
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Thu Sep 21 19:18:12 2017 +0000
upstream commit
- rsa1 is no longer valid;
+ test reverse dynamic forwarding with SOCKS
- Upstream-ID: 9953d09ed9841c44b7dcf7019fa874783a709d89
+ Upstream-Regress-ID: 95cf290470f7e5e2f691e4bc6ba19b91eced2f79
-commit 42b690b4fd0faef78c4d68225948b6e5c46c5163
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 2 14:06:37 2017 +0000
+commit 1b9f321605733754df60fac8c1d3283c89b74455
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Sep 26 16:55:55 2017 +1000
+
+ sync missing changes in dynamic-forward.sh
+
+commit 44fc334c7a9ebdd08addb6d5fa005369897fddeb
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Mon Sep 25 09:48:10 2017 +1000
+
+ Add minimal strsignal for platforms without it.
+
+commit 218e6f98df566fb9bd363f6aa47018cb65ede196
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Sep 24 13:45:34 2017 +0000
upstream commit
- add PubKeyAcceptedKeyTypes to the -o list: scp(1) has
- it, so i guess this should too;
+ fix inverted test on channel open failure path that
+ "upgraded" a transient failure into a fatal error; reported by sthen and also
+ seen by benno@; ok sthen@
- Upstream-ID: 7fab32e869ca5831d09ab0c40d210b461d527a2c
+ Upstream-ID: b58b3fbb79ba224599c6cd6b60c934fc46c68472
-commit d852603214defd93e054de2877b20cc79c19d0c6
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 2 13:44:51 2017 +0000
+commit c704f641f7b8777497dc82e81f2ac89afec7e401
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Sep 24 09:50:01 2017 +0000
upstream commit
- remove now obsolete protocol1 options from the -o
- lists;
+ write the correct buffer when tunnel forwarding; doesn't
+ matter on OpenBSD (they are the same) but does matter on portable where we
+ use an output filter to translate os-specific tun/tap headers
- Upstream-ID: 828e478a440bc5f9947672c392420510a362b3dd
+ Upstream-ID: f1ca94eff48404827b12e1d12f6139ee99a72284
-commit 8b60ce8d8111e604c711c4cdd9579ffe0edced74
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 2 09:05:58 2017 +0000
+commit 55486f5cef117354f0c64f991895835077b7c7f7
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Sep 23 22:04:07 2017 +0000
upstream commit
- more -O shuffle; ok djm
+ fix tunnel forwarding problem introduced in refactor;
+ reported by stsp@ ok markus@
- Upstream-ID: c239991a3a025cdbb030b73e990188dd9bfbeceb
+ Upstream-ID: 81a731cdae1122c8522134095d1a8b60fa9dcd04
-commit 3575f0b12afe6b561681582fd3c34067d1196231
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue May 2 08:54:19 2017 +0000
+commit 609d7a66ce578abf259da2d5f6f68795c2bda731
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Thu Sep 21 19:16:53 2017 +0000
upstream commit
- remove -1 / -2 options; pointed out by jmc@
+ Add 'reverse' dynamic forwarding which combines dynamic
+ forwarding (-D) with remote forwarding (-R) where the remote-forwarded port
+ expects SOCKS-requests.
- Upstream-ID: 65d2a816000741a95df1c7cfdb5fa8469fcc7daa
+ The SSH server code is unchanged and the parsing happens at the SSH
+ clients side. Thus the full SOCKS-request is sent over the forwarded
+ channel and the client parses c->output. Parsing happens in
+ channel_before_prepare_select(), _before_ the select bitmask is
+ computed in the pre[] handlers, but after network input processing
+ in the post[] handlers.
+
+ help and ok djm@
+
+ Upstream-ID: aa25a6a3851064f34fe719e0bf15656ad5a64b89
-commit 4f1ca823bad12e4f9614895eefe0d0073b84a28f
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 2 08:06:33 2017 +0000
+commit 36945fa103176c00b39731e1fc1919a0d0808b81
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Sep 20 05:19:00 2017 +0000
upstream commit
- remove options -12 from usage();
+ Use strsignal in debug message instead of casting for the
+ benefit of portable where sig_atomic_t might not be int. "much nicer"
+ deraadt@
- Upstream-ID: db7ceef25132e63b50ed05289bf447fece1d1270
+ Upstream-ID: 2dac6c1e40511c700bd90664cd263ed2299dcf79
-commit 6b84897f7fd39956b849eac7810319d8a9958568
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Tue May 2 07:13:31 2017 +0000
+commit 3e8d185af326bf183b6f78597d5e3d2eeb2dc40e
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Tue Sep 19 12:10:30 2017 +0000
upstream commit
- tidy up -O somewhat; ok djm
+ Use explicit_bzero() instead of bzero() before free() to
+ prevent the compiler from optimizing away the bzero() call. OK djm@
- Upstream-ID: 804405f716bf7ef15c1f36ab48581ca16aeb4d52
+ Upstream-ID: cdc6197e64c9684c7250e23d60863ee1b53cef1d
-commit d1c6b7fdbdfe4a7a37ecd48a97f0796b061c2868
+commit 5b8da1f53854c0923ec6e927e86709e4d72737b6
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 1 22:09:48 2017 +0000
+Date: Tue Sep 19 04:24:22 2017 +0000
upstream commit
- when freeing a bitmap, zero all it bytes; spotted by Ilya
- Kaliman
+ fix use-after-free in ~^Z escape handler path, introduced
+ in channels.c refactor; spotted by millert@ "makes sense" deraadt@
- Upstream-ID: 834ac024f2c82389d6ea6b1c7d6701b3836e28e4
+ Upstream-ID: 8fa2cdc65c23ad6420c1e59444b0c955b0589b22
-commit 0f163983016c2988a92e039d18a7569f9ea8e071
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 1 14:08:26 2017 +0000
+commit a3839d8d2b89ff1a80cadd4dd654336710de2c9e
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Sep 18 12:03:24 2017 +0000
upstream commit
- this one I did forget to "cvs rm"
+ Prevent type mismatch warning in debug on platforms where
+ sig_atomic_t != int. ok djm@
- Upstream-ID: 5781670c0578fe89663c9085ed3ba477cf7e7913
+ Upstream-ID: 306e2375eb0364a4c68e48f091739bea4f4892ed
-commit 21ed00a8e26fe8a772bcca782175fafc2b0890ed
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 1 09:27:45 2017 +0000
+commit 30484e5e5f0b63d2c6ba32c6b85f06b6c6fa55fc
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Sep 18 09:41:52 2017 +0000
upstream commit
- don't know why cvs didn't exterminate these the first
- time around, I use rm -f and everuthing...
-
- pointed out by sobrado@
+ Add braces missing after channels refactor. ok markus@
- Upstream-ID: a6c44a0c2885330d322ee01fcfd7f6f209b1e15d
+ Upstream-ID: 72ab325c84e010680dbc88f226e2aa96b11a3980
-commit d29ba6f45086703fdcb894532848ada3427dfde6
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon May 1 13:53:07 2017 +1000
+commit b79569190b9b76dfacc6d996faa482f16e8fc026
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Sep 19 12:29:23 2017 +1000
- Define INT32_MAX and INT64_MAX if needed.
+ add freezero(3) replacement
+
+ ok dtucker@
-commit 329037e389f02ec95c8e16bf93ffede94d3d44ce
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon May 1 13:19:41 2017 +1000
+commit 161af8f5ec0961b10cc032efb5cc1b44ced5a92e
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Sep 19 10:18:56 2017 +1000
- Wrap stdint.h in HAVE_STDINT_H
+ move FORTIFY_SOURCE into hardening options group
+
+ It's still on by default, but now it's possible to turn it off using
+ --without-hardening. This is useful since it's known to cause problems
+ with some -fsanitize options. ok dtucker@
-commit f382362e8dfb6b277f16779ab1936399d7f2af78
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 1 02:27:11 2017 +0000
+commit 09eacf856e0fe1a6e3fe597ec8032b7046292914
+Author: bluhm@openbsd.org <bluhm@openbsd.org>
+Date: Wed Sep 13 14:58:26 2017 +0000
upstream commit
- remove unused variable
+ Print SKIPPED if sudo and doas configuration is missing.
+ Prevents that running the regression test with wrong environment is reported
+ as failure. Keep the fatal there to avoid interfering with other setups for
+ portable ssh. OK dtucker@
- Upstream-ID: 66011f00819d0e71b14700449a98414033284516
+ Upstream-Regress-ID: f0dc60023caef496ded341ac5aade2a606fa234e
-commit dd369320d2435b630a5974ab270d686dcd92d024
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:34:55 2017 +0000
+commit cdede10899892f25f1ccdccd7a3fe5e5ef0aa49a
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Aug 7 03:52:55 2017 +0000
upstream commit
- eliminate explicit specification of protocol in tests and
- loops over protocol. We only support SSHv2 now.
+ Remove obsolete privsep=no fallback test.
- Upstream-Regress-ID: 0082838a9b8a382b7ee9cbf0c1b9db727784fadd
+ Upstream-Regress-ID: 7d6e1baa1678ac6be50c2a1555662eb1047638df
-commit 557f921aad004be15805e09fd9572969eb3d9321
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:33:48 2017 +0000
+commit ec218c105daa9f5b192f7aa890fdb2d4fdc4e9d8
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Mon Aug 7 00:53:51 2017 +0000
upstream commit
- remove SSHv1 support from unit tests
+ Remove non-privsep test since disabling privsep is now
+ deprecated.
- Upstream-Regress-ID: 395ca2aa48f1f7d23eefff6cb849ea733ca8bbfe
+ Upstream-Regress-ID: 77ad3f3d8d52e87f514a80f285c6c1229b108ce8
-commit e77e1562716fb3da413e4c2397811017b762f5e3
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon May 1 00:03:18 2017 +0000
+commit 239c57d5bc2253e27e3e6ad7ac52ec8c377ee24e
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jul 28 10:32:08 2017 +0000
upstream commit
- fixup setting ciphercontext->plaintext (lost in SSHv1 purge),
- though it isn't really used for much anymore.
+ Don't call fatal from stop_sshd since it calls cleanup
+ which calls stop_sshd which will probably fail in the same way. Instead,
+ just bail. Differentiate between sshd dying without cleanup and not shutting
+ down.
- Upstream-ID: 859b8bce84ff4865b32097db5430349d04b9b747
-
-commit f7849e6c83a4e0f602dea6c834a24091c622d68e
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon May 1 09:55:56 2017 +1000
-
- remove configure --with-ssh1
+ Upstream-Regress-ID: f97315f538618b349e2b0bea02d6b0c9196c6bc4
-commit f4a6a88ddb6dba6d2f7bfb9e2c9879fcc9633043
+commit aea59a0d9f120f2a87c7f494a0d9c51eaa79b8ba
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:29:10 2017 +0000
+Date: Thu Sep 14 04:32:21 2017 +0000
upstream commit
- flense SSHv1 support from ssh-agent, considerably
- simplifying it
-
- ok markus
+ Revert commitid: gJtIN6rRTS3CHy9b.
- Upstream-ID: 71d772cdcefcb29f76e01252e8361e6fc2dfc365
-
-commit 930e8d2827853bc2e196c20c3e000263cc87fb75
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:28:41 2017 +0000
-
- upstream commit
+ -------------
+ identify the case where SSHFP records are missing but other DNS RR
+ types are present and display a more useful error message for this
+ case; patch by Thordur Bjornsson; bz#2501; ok dtucker@
+ -------------
- obliterate ssh1.h and some dead code that used it
+ This caused unexpected failures when VerifyHostKeyDNS=yes, SSHFP results
+ are missing but the user already has the key in known_hosts
- ok markus@
+ Spotted by dtucker@
- Upstream-ID: 1ca9159a9fb95618f9d51e069ac8e1131a087343
+ Upstream-ID: 97e31742fddaf72046f6ffef091ec0d823299920
-commit a3710d5d529a34b8f56aa62db798c70e85d576a0
+commit 871f1e4374420b07550041b329627c474abc3010
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue Sep 12 18:01:35 2017 +1000
+
+ adapt portable to channels API changes
+
+commit 4ec0bb9f9ad7b4eb0af110fa8eddf8fa199e46bb
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:28:12 2017 +0000
+Date: Tue Sep 12 07:55:48 2017 +0000
upstream commit
- exterminate the -1 flag from scp
-
- ok markus@
+ unused variable
- Upstream-ID: 26d247f7065da15056b209cef5f594ff591b89db
+ Upstream-ID: 2f9ba09f2708993d35eac5aa71df910dcc52bac1
-commit aebd0abfaa8a41e75d50f9f7934267b0a2d9acb4
+commit 9145a73ce2ba30c82bbf91d7205bfd112529449f
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:26:54 2017 +0000
+Date: Tue Sep 12 07:32:04 2017 +0000
upstream commit
- purge the last traces of SSHv1 from the TTY modes
- handling code
-
- ok markus
+ fix tun/tap forwarding case in previous
- Upstream-ID: 963a19f1e06577377c38a3b7ce468f121b966195
+ Upstream-ID: 43ebe37a930320e24bca6900dccc39857840bc53
-commit dfa641f758d4b8b2608ab1b00abaf88df0a8e36a
+commit 9f53229c2ac97dbc6f5a03657de08a1150a9ac7e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:26:16 2017 +0000
+Date: Tue Sep 12 06:35:31 2017 +0000
upstream commit
- remove the (in)famous SSHv1 CRC compensation attack
- detector.
-
- Despite your cameo in The Matrix movies, you will not be missed.
+ Make remote channel ID a u_int
- ok markus
+ Previously we tracked the remote channel IDs in an int, but this is
+ strictly incorrect: the wire protocol uses uint32 and there is nothing
+ in-principle stopping a SSH implementation from sending, say, 0xffff0000.
- Upstream-ID: 44261fce51a56d93cdb2af7b6e184be629f667e0
-
-commit e5d3bd36ef67d82092861f39b5bf422cb12b31a6
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:25:03 2017 +0000
-
- upstream commit
+ In practice everyone numbers their channels sequentially, so this has
+ never been a problem.
- undo some local debugging stuff that I committed by
- accident
+ ok markus@
- Upstream-ID: fe5b31f69a60d47171836911f144acff77810217
+ Upstream-ID: b9f4cd3dc53155b4a5c995c0adba7da760d03e73
-commit 3d6d09f2e90f4ad650ebda6520bf2da446f37f14
+commit dbee4119b502e3f8b6cd3282c69c537fd01d8e16
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:23:54 2017 +0000
+Date: Tue Sep 12 06:32:07 2017 +0000
upstream commit
- remove SSHv1 support from packet and buffer APIs
+ refactor channels.c
+
+ Move static state to a "struct ssh_channels" that is allocated at
+ runtime and tracked as a member of struct ssh.
+
+ Explicitly pass "struct ssh" to all channels functions.
+
+ Replace use of the legacy packet APIs in channels.c.
+
+ Rework sshd_config PermitOpen handling: previously the configuration
+ parser would call directly into the channels layer. After the refactor
+ this is not possible, as the channels structures are allocated at
+ connection time and aren't available when the configuration is parsed.
+ The server config parser now tracks PermitOpen itself and explicitly
+ configures the channels code later.
ok markus@
- Upstream-ID: bfc290053d40b806ecac46317d300677d80e1dc9
+ Upstream-ID: 11828f161656b965cc306576422613614bea2d8f
-commit 05164358577c82de18ed7373196bc7dbd8a3f79c
+commit abd59663df37a42152e37980113ccaa405b9a282
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:21:54 2017 +0000
+Date: Thu Sep 7 23:48:09 2017 +0000
upstream commit
- remove SSHv1-related buffers from client code
+ typo in comment
- Upstream-ID: dca5d01108f891861ceaf7ba1c0f2eb274e0c7dd
+ Upstream-ID: a93b1e6f30f1f9b854b5b964b9fd092d0c422c47
-commit 873d3e7d9a4707d0934fb4c4299354418f91b541
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:18:44 2017 +0000
+commit 149a8cd24ce9dd47c36f571738681df5f31a326c
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Mon Sep 4 06:34:43 2017 +0000
upstream commit
- remove KEY_RSA1
+ tweak previous;
- ok markus@
+ Upstream-ID: bb8cc40b61b15f6a13d81da465ac5bfc65cbfc4b
+
+commit ec9d22cc251cc5acfe7b2bcef9cc7a1fe0e949d8
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Sep 8 12:44:13 2017 +1000
+
+ Fuzzer harnesses for sig verify and pubkey parsing
- Upstream-ID: 7408517b077c892a86b581e19f82a163069bf133
+ These are some basic clang libfuzzer harnesses for signature
+ verification and public key parsing. Some assembly (metaphorical)
+ required.
-commit 788ac799a6efa40517f2ac0d895a610394298ffc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:18:22 2017 +0000
+commit de35c382894964a896a63ecd5607d3a3b93af75d
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Sep 8 12:38:31 2017 +1000
- upstream commit
+ Give configure ability to set CFLAGS/LDFLAGS later
- remove SSHv1 configuration options and man pages bits
+ Some CFLAGS/LDFLAGS may disrupt the configure script's operation,
+ in particular santization and fuzzer options that break assumptions
+ about memory and file descriptor dispositions.
- ok markus@
+ This adds two flags to configure --with-cflags-after and
+ --with-ldflags-after that allow specifying additional compiler and
+ linker options that are added to the resultant Makefiles but not
+ used in the configure run itself.
- Upstream-ID: 84638c23546c056727b7a7d653c72574e0f19424
+ E.g.
+
+ env CC=clang-3.9 ./configure \
+ --with-cflags-after=-fsantize=address \
+ --with-ldflags-after="-g -fsanitize=address"
-commit e6882463a8ae0594aacb6d6575a6318a41973d84
+commit 22376d27a349f62c502fec3396dfe0fdcb2a40b7
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:17:37 2017 +0000
+Date: Sun Sep 3 23:33:13 2017 +0000
upstream commit
- remove SSH1 make flag and associated files ok markus@
+ Expand ssh_config's StrictModes option with two new
+ settings:
- Upstream-ID: ba9feacc5787337c413db7cf26ea3d53f854cfef
+ StrictModes=accept-new will automatically accept hitherto-unseen keys
+ but will refuse connections for changed or invalid hostkeys.
+
+ StrictModes=off is the same as StrictModes=no
+
+ Motivation:
+
+ StrictModes=no combines two behaviours for host key processing:
+ automatically learning new hostkeys and continuing to connect to hosts
+ with invalid/changed hostkeys. The latter behaviour is quite dangerous
+ since it removes most of the protections the SSH protocol is supposed to
+ provide.
+
+ Quite a few users want to automatically learn hostkeys however, so
+ this makes that feature available with less danger.
+
+ At some point in the future, StrictModes=no will change to be a synonym
+ for accept-new, with its current behaviour remaining available via
+ StrictModes=off.
+
+ bz#2400, suggested by Michael Samuel; ok markus
+
+ Upstream-ID: 0f55502bf75fc93a74fb9853264a8276b9680b64
-commit cdccebdf85204bf7542b7fcc1aa2ea3f36661833
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:15:04 2017 +0000
+commit ff3c42384033514e248ba5d7376aa033f4a2b99a
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Sep 1 15:41:26 2017 +0000
upstream commit
- remove SSHv1 ciphers; ok markus@
+ remove blank line;
- Upstream-ID: e5ebc5e540d7f23a8c1266db1839794d4d177890
+ Upstream-ID: 2f46b51a0ddb3730020791719e94d3e418e9f423
-commit 97f4d3083b036ce3e68d6346a6140a22123d5864
+commit b828605d51f57851316d7ba402b4ae06cf37c55d
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:13:25 2017 +0000
+Date: Fri Sep 1 05:53:56 2017 +0000
upstream commit
- remove compat20/compat13/compat15 variables
-
- ok markus@
+ identify the case where SSHFP records are missing but
+ other DNS RR types are present and display a more useful error message for
+ this case; patch by Thordur Bjornsson; bz#2501; ok dtucker@
- Upstream-ID: 43802c035ceb3fef6c50c400e4ecabf12354691c
+ Upstream-ID: 8f7a5a8344f684823d8317a9708b63e75be2c244
-commit 99f95ba82673d33215dce17bfa1512b57f54ec09
+commit 8042bad97e2789a50e8f742c3bcd665ebf0add32
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:11:45 2017 +0000
+Date: Fri Sep 1 05:50:48 2017 +0000
upstream commit
- remove options.protocol and client Protocol
- configuration knob
-
- ok markus@
+ document available AuthenticationMethods; bz#2453 ok
+ dtucker@
- Upstream-ID: 5a967f5d06e2d004b0235457b6de3a9a314e9366
+ Upstream-ID: 2c70576f237bb699aff59889dbf2acba4276d3d0
-commit 56912dea6ef63dae4eb1194e5d88973a7c6c5740
+commit 71e5a536ec815d542b199f2ae6d646c0db9f1b58
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Apr 30 23:10:43 2017 +0000
+Date: Wed Aug 30 03:59:08 2017 +0000
upstream commit
- unifdef WITH_SSH1 ok markus@
+ pass packet state down to some of the channels function
+ (more to come...); ok markus@
- Upstream-ID: 9716e62a883ef8826c57f4d33b4a81a9cc7755c7
+ Upstream-ID: d8ce7a94f4059d7ac1e01fb0eb01de0c4b36c81b
-commit d4084cd230f7319056559b00db8b99296dad49d5
+commit 6227fe5b362239c872b91bbdee4bf63cf85aebc5
Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Sat Apr 29 06:06:01 2017 +0000
+Date: Tue Aug 29 13:05:58 2017 +0000
upstream commit
- tweak previous;
+ sort options;
- Upstream-ID: a3abc6857455299aa42a046d232b7984568bceb9
+ Upstream-ID: cf21d68cf54e81968bca629aaeddc87f0c684f3c
-commit 249516e428e8461b46340a5df5d5ed1fbad2ccce
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Apr 29 04:12:25 2017 +0000
+commit 530591a5795a02d01c78877d58604723918aac87
+Author: dlg@openbsd.org <dlg@openbsd.org>
+Date: Tue Aug 29 09:42:29 2017 +0000
upstream commit
- allow ssh-keygen to include arbitrary string or flag
- certificate extensions and critical options. ok markus@ dtucker@
+ add a -q option to ssh-add to make it quiet on success.
- Upstream-ID: 2cf28dd6c5489eb9fc136e0b667ac3ea10241646
+ if you want to silence ssh-add without this you generally redirect
+ the output to /dev/null, but that can hide error output which you
+ should see.
+
+ ok djm@
+
+ Upstream-ID: 2f31b9b13f99dcf587e9a8ba443458e6c0d8997c
-commit 47a287bb6ac936c26b4f3ae63279c02902ded3b9
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Apr 28 06:15:03 2017 +0000
+commit a54eb27dd64b5eca3ba94e15cec3535124bd5029
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Sun Aug 27 00:38:41 2017 +0000
upstream commit
- sort;
+ Increase the buffer sizes for user prompts to ensure that
+ they won't be truncated by snprintf. Based on patch from cjwatson at
+ debian.org via bz#2768, ok djm@
- Upstream-ID: 7e6b56e52b039cf44d0418e9de9aca20a2d2d15a
+ Upstream-ID: 6ffacf1abec8f40b469de5b94bfb29997d96af3e
-commit 36465a76a79ad5040800711b41cf5f32249d5120
+commit dd9d9b3381a4597b840d480b043823112039327e
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 28 14:44:28 2017 +1000
+Date: Mon Aug 28 16:48:27 2017 +1000
- Typo.
+ Switch Capsicum header to sys/capsicum.h.
- Upstream-Regress-ID: 1e6b51ddf767cbad0a4e63eb08026c127e654308
+ FreeBSD's <sys/capability.h> was renamed to <sys/capsicum.h> in 2014 to
+ avoid future conflicts with POSIX capabilities (the last release that
+ didn't have it was 9.3) so switch to that. Patch from des at des.no.
-commit 9d18cb7bdeb00b20205fd13d412aae8c0e0457ed
+commit f5e917ab105af5dd6429348d9bc463e52b263f92
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 28 14:41:17 2017 +1000
+Date: Sun Aug 27 08:55:40 2017 +1000
- Add 2 regress commits I applied by hand.
+ Add missing includes for bsd-err.c.
- Upstream-Regress-ID: 30c20180c87cbc99fa1020489fe7fd8245b6420c
- Upstream-Regress-ID: 1e6b51ddf767cbad0a4e63eb08026c127e654308
+ Patch from cjwatson at debian.org via bz#2767.
-commit 9504ea6b27f9f0ece64e88582ebb9235e664a100
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 28 14:33:43 2017 +1000
+commit 878e029797cfc9754771d6f6ea17f8c89e11d225
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Aug 25 13:25:01 2017 +1000
- Merge integrity.sh rev 1.22.
+ Split platform_sys_dir_uid into its own file
- Merge missing bits from Colin Watson's patch in bz#2658 which make integrity
- tests more robust against timeouts. ok djm@
+ platform.o is too heavy for libssh.a use; it calls into the server on
+ many platforms. Move just the function needed by misc.c into its own
+ file.
-commit 06ec837a34542627e2183a412d6a9d2236f22140
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Apr 28 14:30:03 2017 +1000
+commit 07949bfe9133234eddd01715592aa0dde67745f0
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed Aug 23 20:13:18 2017 +1000
- Id sync for integrity.sh rev 1.21 which pulls in some shell portability fixes
+ misc.c needs functions from platform.c now
-commit e0194b471efe7d3daedc9cc66686cb1ab69d3be8
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Mon Apr 17 11:02:31 2017 +0000
+commit b074c3c3f820000a21953441cea7699c4b17d72f
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Aug 18 05:48:04 2017 +0000
+
+ upstream commit
+
+ add a "quiet" flag to exited_cleanly() that supresses
+ errors about exit status (failure due to signal is still reported)
+
+ Upstream-ID: db85c39c3aa08e6ff67fc1fb4ffa89f807a9d2f0
+
+commit de4ae07f12dabf8815ecede54235fce5d22e3f63
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Aug 18 05:36:45 2017 +0000
+
+ upstream commit
+
+ Move several subprocess-related functions from various
+ locations to misc.c. Extend subprocess() to offer a little more control over
+ stdio disposition.
+
+ feedback & ok dtucker@
+
+ Upstream-ID: 3573dd7109d13ef9bd3bed93a3deb170fbfce049
+
+commit 643c2ad82910691b2240551ea8b14472f60b5078
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Aug 12 06:46:01 2017 +0000
upstream commit
- Change COMPILER_VERSION tests which limited additional
- warnings to gcc4 to instead skip them on gcc3 as clang can handle
- -Wpointer-sign and -Wold-style-definition.
+ make "--" before the hostname terminate command-line
+ option processing completely; previous behaviour would not prevent further
+ options appearing after the hostname (ssh has a supported options after the
+ hostname for >20 years, so that's too late to change).
- Upstream-Regress-ID: e48d7dc13e48d9334b8195ef884dfbc51316012f
+ ok deraadt@
+
+ Upstream-ID: ef5ee50571b98ad94dcdf8282204e877ec88ad89
-commit 6830be90e71f46bcd182a9202b151eaf2b299434
+commit 0f3455356bc284d7c6f4d3c1614d31161bd5dcc2
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Apr 28 03:24:53 2017 +0000
+Date: Sat Aug 12 06:42:52 2017 +0000
upstream commit
- include key fingerprint in "Offering public key" debug
- message
+ Switch from aes256-cbc to aes256-ctr for encrypting
+ new-style private keys. The latter having the advantage of being supported
+ for no-OpenSSL builds; bz#2754 ok markus@
- Upstream-ID: 964749f820c2ed4cf6a866268b1a05e907315c52
+ Upstream-ID: 54179a2afd28f93470471030567ac40431e56909
-commit 066437187e16dcafcbc19f9402ef0e6575899b1d
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Fri Apr 28 03:21:12 2017 +0000
+commit c4972d0a9bd6f898462906b4827e09b7caea2d9b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Aug 11 04:47:12 2017 +0000
upstream commit
- Avoid relying on implementation-specific behavior when
- detecting whether the timestamp or file size overflowed. If time_t and off_t
- are not either 32-bit or 64-bit scp will exit with an error. OK djm@
+ refuse to a private keys when its corresponding .pub key
+ does not match. bz#2737 ok dtucker@
- Upstream-ID: f31caae73ddab6df496b7bbbf7da431e267ad135
+ Upstream-ID: 54ff5e2db00037f9db8d61690f26ef8f16e0d913
-commit 68d3a2a059183ebd83b15e54984ffaced04d2742
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Apr 28 03:20:27 2017 +0000
+commit 4b3ecbb663c919132dddb3758e17a23089413519
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Aug 11 04:41:08 2017 +0000
upstream commit
- Add SyslogFacility option to ssh(1) matching the
- equivalent option in sshd(8). bz#2705, patch from erahn at arista.com, ok
- djm@
+ don't print verbose error message when ssh disconnects
+ under sftp; bz#2750; ok dtucker@
- Upstream-ID: d5115c2c0193ceb056ed857813b2a7222abda9ed
+ Upstream-ID: 6d83708aed77b933c47cf155a87dc753ec01f370
-commit e13aad66e73a14b062d13aee4e98f1e21a3f6a14
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Thu Apr 27 13:40:05 2017 +0000
+commit 42a8f8bc288ef8cac504c5c73f09ed610bc74a34
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Aug 11 04:16:35 2017 +0000
upstream commit
- remove a static array unused since rev 1.306 spotted by
- clang ok djm@
+ Tweak previous keepalive commit: if last_time + keepalive
+ <= now instead of just "<" so client_alive_check will fire if the select
+ happens to return on exact second of the timeout. ok djm@
- Upstream-ID: 249b3eed2446f6074ba2219ccc46919dd235a7b8
+ Upstream-ID: e02756bd6038d11bb8522bfd75a4761c3a684fcc
-commit 91bd2181866659f00714903e78e1c3edd4c45f3d
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Thu Apr 27 11:53:12 2017 +0000
+commit b60ff20051ef96dfb207b6bfa45c0ad6c34a542a
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Aug 11 03:58:36 2017 +0000
upstream commit
- Avoid potential signed int overflow when parsing the file
- size. Use strtoul() instead of parsing manually. OK djm@
+ Keep track of the last time we actually heard from the
+ client and use this to also schedule a client_alive_check(). Prevents
+ activity on a forwarded port from indefinitely preventing the select timeout
+ so that client_alive_check() will eventually (although not optimally) be
+ called.
- Upstream-ID: 1f82640861c7d905bbb05e7d935d46b0419ced02
+ Analysis by willchan at google com via bz#2756, feedback & ok djm@
+
+ Upstream-ID: c08721e0bbda55c6d18e2760f3fe1b17fb71169e
-commit 17a54a03f5a1d35e33cc24e22cd7a9d0f6865dc4
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Apr 25 08:32:27 2017 +1000
+commit 94bc1e7ffba3cbdea8c7dcdab8376bf29283128f
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jul 28 14:50:59 2017 +1000
- Fix typo in "socketcall".
+ Expose list of completed auth methods to PAM
- Pointed out by jjelen at redhat.com.
+ bz#2408; ok dtucker@
-commit 8b0eee148f7cf8b248c30d1bae57300f2cc5aafd
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Apr 24 19:40:31 2017 +1000
+commit c78e6eec78c88acf8d51db90ae05a3e39458603d
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jul 21 14:38:16 2017 +1000
- Deny socketcall in seccomp filter on ppc64le.
+ fix problems in tunnel forwarding portability code
- OpenSSL is using socket() calls (in FIPS mode) when handling ECDSA keys
- in privsep child. The socket() syscall is already denied in the seccomp
- filter, but in ppc64le kernel, it is implemented using socketcall()
- syscall, which is not denied yet (only SYS_SHUTDOWN is allowed) and
- therefore fails hard.
+ This fixes a few problems in the tun forwarding code, mostly to do
+ with host/network byte order confusion.
- Patch from jjelen at redhat.com.
+ Based on a report and patch by stepe AT centaurus.uberspace.de;
+ bz#2735; ok dtucker@
-commit f8500b2be599053daa05248a86a743232ec6a536
-Author: schwarze@openbsd.org <schwarze@openbsd.org>
-Date: Mon Apr 17 14:31:23 2017 +0000
+commit 2985d4062ebf4204bbd373456a810d558698f9f5
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Tue Jul 25 09:22:25 2017 +0000
upstream commit
- Recognize nl_langinfo(CODESET) return values "646" and ""
- as aliases for "US-ASCII", useful for different versions of NetBSD and
- Solaris. Found by dtucker@ and by Tom G. Christensen <tgc at jupiterrise dot
- com>. OK dtucker@ deraadt@
+ Make WinSCP patterns for SSH_OLD_DHGEX more specific to
+ exclude WinSCP 5.10.x and up. bz#2748, from martin at winscp.net, ok djm@
- Upstream-ID: 38c2133817cbcae75c88c63599ac54228f0fa384
+ Upstream-ID: 6fd7c32e99af3952db007aa180e73142ddbc741a
-commit 7480dfedf8c5c93baaabef444b3def9331e86ad5
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Mon Apr 17 11:02:31 2017 +0000
+commit 9f0e44e1a0439ff4646495d5735baa61138930a9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon Jul 24 04:34:28 2017 +0000
upstream commit
- Change COMPILER_VERSION tests which limited additional
- warnings to gcc4 to instead skip them on gcc3 as clang can handle
- -Wpointer-sign and -Wold-style-definition.
+ g/c unused variable; make a little more portable
- Upstream-ID: 5cbe348aa76dc1adf55be6c0e388fafaa945439a
+ Upstream-ID: 3f5980481551cb823c6fb2858900f93fa9217dea
-commit 4d827f0d75a53d3952288ab882efbddea7ffadfe
+commit 51676ec61491ec6d7cbd06082034e29b377b3bf6
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Apr 4 00:24:56 2017 +0000
+Date: Sun Jul 23 23:37:02 2017 +0000
upstream commit
- disallow creation (of empty files) in read-only mode;
- reported by Michal Zalewski, feedback & ok deraadt@
+ Allow IPQoS=none in ssh/sshd to not set an explicit
+ ToS/DSCP value and just use the operating system default; ok dtucker@
- Upstream-ID: 5d9c8f2fa8511d4ecf95322994ffe73e9283899b
+ Upstream-ID: 77906ff8c7b660b02ba7cb1e47b17d66f54f1f7e
-commit ef47843af0a904a21c920e619c5aec97b65dd9ac
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Sun Mar 26 00:18:52 2017 +0000
+commit 6c1fbd5a50d8d2415f06c920dd3b1279b741072d
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jul 21 14:24:26 2017 +1000
+
+ mention libedit
+
+commit dc2bd308768386b02c7337120203ca477e67ba62
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed Jul 19 08:30:41 2017 +0000
upstream commit
- incorrect renditions of this quote bother me
+ fix support for unknown key types; ok djm@
- Upstream-ID: 1662be3ebb7a71d543da088119c31d4d463a9e49
+ Upstream-ID: 53fb29394ed04d616d65b3748dee5aa06b07ab48
-commit d9048861bea842c4eba9c2dbbf97064cc2a5ef02
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Mar 31 11:04:43 2017 +1100
+commit fd0e8fa5f89d21290b1fb5f9d110ca4f113d81d9
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jul 19 01:15:02 2017 +0000
- Check for and use gcc's -pipe.
+ upstream commit
- Speeds up configure and build by a couple of percent. ok djm@
-
-commit 282cad2240c4fbc104c2f2df86d688192cbbe4bb
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 16:34:44 2017 +1100
-
- Import fmt_scaled.c rev 1.16 from OpenBSD.
+ switch from select() to poll() for the ssh-agent
+ mainloop; ok markus
- Fix overly-conservative overflow checks on mulitplications and add checks
- on additions. This allows scan_scaled to work up to +/-LLONG_MAX (LLONG_MIN
- will still be flagged as a range error). ok millert@
+ Upstream-ID: 4a94888ee67b3fd948fd10693973beb12f802448
-commit c73a229e4edf98920f395e19fd310684fc6bb951
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 16:34:02 2017 +1100
+commit b1e72df2b813ecc15bd0152167bf4af5f91c36d3
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jul 14 03:18:21 2017 +0000
- Import fmt_scaled.c rev 1.15 from OpenBSD.
+ upstream commit
- Collapse underflow and overflow checks into a single block.
- ok djm@ millert@
-
-commit d427b73bf5a564f663d16546dbcbd84ba8b9d4af
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 16:32:57 2017 +1100
-
- Import fmt_scaled.c rev 1.14 from OpenBSD.
+ Make ""Killed by signal 1" LogLevel verbose so it's not
+ shown at the default level. Prevents it from appearing during ssh -J and
+ equivalent ProxyCommand configs. bz#1906, bz#2744, feedback&ok markus@
- Catch integer underflow in scan_scaled reported by Nicolas Iooss.
- ok deraadt@ djm@
+ Upstream-ID: debfaa7e859b272246c2f2633335d288d2e2ae28
-commit d13281f2964abc5f2e535e1613c77fc61b0c53e7
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 12:39:39 2017 +1100
+commit 1f3d202770a08ee6752ed2a234b7ca6f180eb498
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Thu Jul 13 19:16:33 2017 +0000
- Don't check privsep user or path when unprivileged
+ upstream commit
- If running with privsep (mandatory now) as a non-privileged user, we
- don't chroot or change to an unprivileged user however we still checked
- the existence of the user and directory. Don't do those checks if we're
- not going to use them. Based in part on a patch from Lionel Fourquaux
- via Corinna Vinschen, ok djm@
-
-commit f2742a481fe151e493765a3fbdef200df2ea7037
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 10:50:31 2017 +1100
-
- Remove SHA256 EVP wrapper implementation.
+ man pages with pseudo synopses which list filenames end
+ up creating very ugly output in man -k; after some discussion with ingo, we
+ feel the simplest fix is to remove such SYNOPSIS sections: the info is hardly
+ helpful at page top, is contained already in FILES, and there are
+ sufficiently few that just zapping them is simple;
- All supported versions of OpenSSL should now have SHA256 so remove our
- EVP wrapper implementaion. ok djm@
-
-commit 5346f271fc76549caf4a8e65b5fba319be422fe9
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 10:23:58 2017 +1100
-
- Remove check for OpenSSL < 0.9.8g.
+ ok schwarze, who also helpfully ran things through a build to check
+ output;
- We no longer support OpenSSL < 1.0.1 so remove check for unreliable ECC
- in OpenSSL < 0.9.8g.
+ Upstream-ID: 3e211b99457e2f4c925c5927d608e6f97431336c
-commit 8fed0a5fe7b4e78a6810b133d8e91be9742ee0a1
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 10:16:15 2017 +1100
+commit 7f13a4827fb28957161de4249bd6d71954f1f2ed
+Author: espie@openbsd.org <espie@openbsd.org>
+Date: Mon Jul 10 14:09:59 2017 +0000
- Remove compat code for OpenSSL < 0.9.7.
+ upstream commit
- Resyncs that code with OpenBSD upstream.
-
-commit 608ec1f62ff22fdccc3952e51463d79c43cbd0d3
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Mar 29 09:50:54 2017 +1100
-
- Remove SSHv1 code path.
+ zap redundant Makefile variables. okay djm@
- Server-side support for Protocol 1 has been removed so remove !compat20
- PAM code path.
+ Upstream-ID: e39b3902fe1d6c4a7ba6a3c58e072219f3c1e604
-commit 7af27bf538cbc493d609753f9a6d43168d438f1b
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Mar 24 09:44:56 2017 +1100
+commit dc44dd3a9e2c9795394e6a7e1e71c929cbc70ce0
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Jul 8 18:32:54 2017 +0000
- Enable ldns when using ldns-config.
+ upstream commit
- Actually enable ldns when attempting to use ldns-config. bz#2697, patch
- from fredrik at fornwall.net.
-
-commit 58b8cfa2a062b72139d7229ae8de567f55776f24
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Mar 22 12:43:02 2017 +1100
-
- Missing header on Linux/s390
+ slightly rework previous, to avoid an article issue;
- Patch from Jakub Jelen
+ Upstream-ID: 15a315f0460ddd3d4e2ade1f16d6c640a8c41b30
-commit 096fb65084593f9f3c1fc91b6d9052759a272a00
+commit 853edbe057a84ebd0024c8003e4da21bf2b469f7
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Mar 20 22:08:06 2017 +0000
+Date: Fri Jul 7 03:53:12 2017 +0000
upstream commit
- remove /usr/bin/time calls around tests, makes diffing test
- runs harder. Based on patch from Mike Frysinger
-
- Upstream-Regress-ID: 81c1083b14dcf473b23d2817882f40b346ebc95c
-
-commit 6b853c6f8ba5eecc50f3b57af8e63f8184eb0fa6
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 21 08:47:55 2017 +1100
-
- Fix syntax error on Linux/X32
+ When generating all hostkeys (ssh-keygen -A), clobber
+ existing keys if they exist but are zero length. zero-length keys could
+ previously be made if ssh-keygen failed part way through generating them, so
+ avoid that case too. bz#2561 reported by Krzysztof Cieplucha; ok dtucker@
- Patch from Mike Frysinger
-
-commit d38f05dbdd291212bc95ea80648b72b7177e9f4e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Mar 20 13:38:27 2017 +1100
-
- Add llabs() implementation.
-
-commit 72536316a219b7394996a74691a5d4ec197480f7
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 20 12:23:04 2017 +1100
-
- crank version numbers
+ Upstream-ID: f662201c28ab8e1f086b5d43c59cddab5ade4044
-commit 3be52bc36bdfd24ded7e0f46999e7db520fb4e3f
+commit 43616876ba68a2ffaece6a6c792def4b039f2d6e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Mar 20 01:18:59 2017 +0000
+Date: Sat Jul 1 22:55:44 2017 +0000
upstream commit
- openssh-7.5
+ actually remove these files
- Upstream-ID: b8b9a4a949427c393cd868215e1724ceb3467ee5
+ Upstream-ID: 1bd41cba06a7752de4df304305a8153ebfb6b0ac
-commit db84e52fe9cfad57f22e7e23c5fbf00092385129
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 20 12:07:20 2017 +1100
+commit 83fa3a044891887369ce8b487ce88d713a04df48
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jul 1 13:50:45 2017 +0000
- I'm a doofus.
+ upstream commit
+
+ remove post-SSHv1 removal dead code from rsa.c and merge
+ the remaining bit that it still used into ssh-rsa.c; ok markus
- Unbreak obvious syntax error.
+ Upstream-ID: ac8a048d24dcd89594b0052ea5e3404b473bfa2f
-commit 89f04852db27643717c9c3a2b0dde97ae50099ee
+commit 738c73dca2c99ee78c531b4cbeefc2008fe438f0
Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 20 11:53:34 2017 +1100
+Date: Fri Jul 14 14:26:36 2017 +1000
- on Cygwin, check paths from server for backslashes
-
- Pointed out by Jann Horn of Google Project Zero
+ make explicit_bzero/memset safe for sz=0
-commit 7ef1f9bafc2cc8d97ff2fbd4f280002b6e8ea5d9
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 20 11:48:34 2017 +1100
+commit 8433d51e067e0829f5521c0c646b6fd3fe17e732
+Author: Tim Rice <tim@multitalents.net>
+Date: Tue Jul 11 18:47:56 2017 -0700
- Yet another synonym for ASCII: "646"
-
- Used by NetBSD; this unbreaks mprintf() and friends there for the C
- locale (caught by dtucker@ and his menagerie of test systems).
+ modified: configure.ac
+ UnixWare needs BROKEN_TCGETATTR_ICANON like Solaris
+ Analysis by Robbie Zhang
-commit 9165abfea3f68a0c684a6ed2e575e59bc31a3a6b
+commit ff3507aea9c7d30cd098e7801e156c68faff7cc7
Author: Damien Miller <djm@mindrot.org>
-Date: Mon Mar 20 09:58:34 2017 +1100
+Date: Fri Jul 7 11:21:27 2017 +1000
- create test mux socket in /tmp
-
- Creating the socket in $OBJ could blow past the (quite limited)
- path limit for Unix domain sockets. As a bandaid for bz#2660,
- reported by Colin Watson; ok dtucker@
+ typo
-commit 2adbe1e63bc313d03e8e84e652cc623af8ebb163
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Mar 15 07:07:39 2017 +0000
+commit d79bceb9311a9c137d268f5bc481705db4151810
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jun 30 04:17:23 2017 +0000
upstream commit
- disallow KEXINIT before NEWKEYS; ok djm; report by
- vegard.nossum at oracle.com
+ Only call close once in confree(). ssh_packet_close will
+ close the FD so only explicitly close non-SSH channels. bz#2734, from
+ bagajjal at microsoft.com, ok djm@
- Upstream-ID: 3668852d1f145050e62f1da08917de34cb0c5234
-
-commit 2fbf91684d76d38b9cf06550b69c9e41bca5a71c
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Mar 16 14:05:46 2017 +1100
-
- Include includes.h for compat bits.
+ Upstream-ID: a81ce0c8b023527167739fccf1732b154718ab02
-commit b55f634e96b9c5b0cd991e23a9ca181bec4bdbad
+commit 197dc9728f062e23ce374f44c95a2b5f9ffa4075
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Mar 16 13:45:17 2017 +1100
-
- Wrap stdint.h in #ifdef HAVE_STDINT_H
-
-commit 55a1117d7342a0bf8b793250cf314bab6b482b99
-Author: Damien Miller <djm@mindrot.org>
-Date: Thu Mar 16 11:22:42 2017 +1100
+Date: Thu Jun 29 15:40:25 2017 +1000
- Adapt Cygwin config script to privsep knob removal
-
- Patch from Corinna Vinschen.
+ Update link for my patches.
-commit 1a321bfdb91defe3c4d9cca5651724ae167e5436
-Author: deraadt@openbsd.org <deraadt@openbsd.org>
-Date: Wed Mar 15 03:52:30 2017 +0000
+commit a98339edbc1fc21342a390f345179a9c3031bef7
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jun 28 01:09:22 2017 +0000
upstream commit
- accidents happen to the best of us; ok djm
+ Allow ssh-keygen to use a key held in ssh-agent as a CA when
+ signing certificates. bz#2377 ok markus
- Upstream-ID: b7a9dbd71011ffde95e06f6945fe7197dedd1604
+ Upstream-ID: fb42e920b592edcbb5b50465739a867c09329c8f
-commit 25f837646be8c2017c914d34be71ca435dfc0e07
+commit c9cdef35524bd59007e17d5bd2502dade69e2dfb
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 15 02:25:09 2017 +0000
+Date: Sat Jun 24 06:35:24 2017 +0000
upstream commit
- fix regression in 7.4: deletion of PKCS#11-hosted keys
- would fail unless they were specified by full physical pathname. Report and
- fix from Jakub Jelen via bz#2682; ok dtucker@
+ regress test for ExposeAuthInfo
- Upstream-ID: 5b5bc20ca11cacb5d5eb29c3f93fd18425552268
+ Upstream-Regress-ID: 190e5b6866376f4061c411ab157ca4d4e7ae86fd
-commit a8c5eeacf032a7d3408957e45dd7603cc1baf55f
+commit f17ee61cad25d210edab69d04ed447ad55fe80c1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 15 02:19:09 2017 +0000
+Date: Sat Jun 24 07:08:57 2017 +0000
upstream commit
- Fix segfault when sshd attempts to load RSA1 keys (can
- only happen when protocol v.1 support is enabled for the client). Reported by
- Jakub Jelen in bz#2686; ok dtucker
+ correct env var name
- Upstream-ID: 8fdaec2ba4b5f65db1d094f6714ce64b25d871d7
+ Upstream-ID: 721e761c2b1d6a4dcf700179f16fd53a1dadb313
-commit 66705948c0639a7061a0d0753266da7685badfec
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Mar 14 07:19:07 2017 +0000
+commit 40962198e3b132cecdb32e9350acd4294e6a1082
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Jun 24 06:57:04 2017 +0000
upstream commit
- Mark the sshd_config UsePrivilegeSeparation option as
- deprecated, effectively making privsep mandatory in sandboxing mode. ok
- markus@ deraadt@
-
- (note: this doesn't remove the !privsep code paths, though that will
- happen eventually).
-
- Upstream-ID: b4c52666256c4dd865f8ce9431af5d6ce2d74a0a
-
-commit f86586b03fe6cd8f595289bde200a94bc2c191af
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 14 18:26:29 2017 +1100
-
- Make seccomp-bpf sandbox work on Linux/X32
+ spelling;
- Allow clock_gettime syscall with X32 bit masked off. Apparently
- this is required for at least some kernel versions. bz#2142
- Patch mostly by Colin Watson. ok dtucker@
-
-commit 2429cf78dd2a9741ce27ba25ac41c535274a0af6
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 14 18:01:52 2017 +1100
-
- require OpenSSL >=1.0.1
+ Upstream-ID: 606f933c8e2d0be902ea663946bc15e3eee40b25
-commit e3ea335abeab731c68f2b2141bee85a4b0bf680f
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 14 17:48:43 2017 +1100
+commit 33f86265d7e8a0e88d3a81745d746efbdd397370
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 24 06:38:11 2017 +0000
- Remove macro trickery; no binary change
-
- This stops the SC_ALLOW(), SC_ALLOW_ARG() and SC_DENY() macros
- prepending __NR_ to the syscall number parameter and just makes
- them explicit in the macro invocations.
+ upstream commit
- No binary change in stripped object file before/after.
-
-commit 5f1596e11d55539678c41f68aed358628d33d86f
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 14 13:15:18 2017 +1100
-
- support ioctls for ICA crypto card on Linux/s390
+ don't pass pointer to struct sshcipher between privsep
+ processes, just redo the lookup in each using the already-passed cipher name.
+ bz#2704 based on patch from Brooks Davis; ok markus dtucker
- Based on patch from Eduardo Barretto; ok dtucker@
-
-commit b1b22dd0df2668b322dda174e501dccba2cf5c44
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Mar 14 14:19:36 2017 +1100
-
- Plumb conversion test into makefile.
+ Upstream-ID: 2eab434c09bdf549dafd7da3e32a0d2d540adbe0
-commit f57783f1ddfb4cdfbd612c6beb5ec01cb5b9a6b9
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Mar 14 01:20:29 2017 +0000
+commit 8f574959272ac7fe9239c4f5d10fd913f8920ab0
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 24 06:34:38 2017 +0000
upstream commit
- Add unit test for convtime().
+ refactor authentication logging
- Upstream-Regress-ID: 8717bc0ca4c21120f6dd3a1d3b7a363f707c31e1
-
-commit 8884b7247d094cd11ff9e39c325ba928c5bdbc6c
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Mar 14 01:10:07 2017 +0000
-
- upstream commit
+ optionally record successful auth methods and public credentials
+ used in a file accessible to user sessions
- Add ASSERT_LONG_* helpers.
+ feedback and ok markus@
- Upstream-Regress-ID: fe15beaea8f5063c7f21b0660c722648e3d76431
+ Upstream-ID: 090b93036967015717b9a54fd0467875ae9d32fb
-commit c6774d21185220c0ba11e8fd204bf0ad1a432071
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Mar 14 00:55:37 2017 +0000
+commit e2004d4bb7eb01c663dd3a3e7eb224f1ccdc9bba
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Jun 24 06:28:50 2017 +0000
upstream commit
- Fix convtime() overflow test on boundary condition,
- spotted by & ok djm.
+ word fix;
- Upstream-ID: 51f14c507ea87a3022e63f574100613ab2ba5708
+ Upstream-ID: 8539bdaf2366603a34a9b2f034527ca13bb795c5
-commit f5746b40cfe6d767c8e128fe50c43274b31cd594
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Mar 14 00:25:03 2017 +0000
+commit 4540428cd0adf039bcf5a8a27f2d5cdf09191513
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 24 05:37:44 2017 +0000
upstream commit
- Check for integer overflow when parsing times in
- convtime(). Reported by nicolas.iooss at m4x.org, ok djm@
+ switch sshconnect.c from (slightly abused) select() to
+ poll(); ok deraadt@ a while back
- Upstream-ID: 35e6a4e98f6fa24df50bfb8ba1307cf70e966f13
-
-commit f5907982f42a8d88a430b8a46752cbb7859ba979
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Mar 14 13:38:15 2017 +1100
-
- Add a "unit" target to run only unit tests.
+ Upstream-ID: efc1937fc591bbe70ac9e9542bb984f354c8c175
-commit 9e96b41682aed793fadbea5ccd472f862179fb02
-Author: Damien Miller <djm@mindrot.org>
-Date: Tue Mar 14 12:24:47 2017 +1100
+commit 6f8ca3b92540fa1a9b91670edc98d15448e3d765
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sat Jun 24 05:35:05 2017 +0000
- Fix weakness in seccomp-bpf sandbox arg inspection
-
- Syscall arguments are passed via an array of 64-bit values in struct
- seccomp_data, but we were only inspecting the bottom 32 bits and not
- even those correctly for BE systems.
+ upstream commit
- Fortunately, the only case argument inspection was used was in the
- socketcall filtering so using this for sandbox escape seems
- impossible.
+ use HostKeyAlias if specified instead of hostname for
+ matching host certificate principal names; bz#2728; ok dtucker@
- ok dtucker
+ Upstream-ID: dc2e11c83ae9201bbe74872a0c895ae9725536dd
-commit 8ff3fc3f2f7c13e8968717bc2b895ee32c441275
+commit 8904ffce057b80a7472955f1ec00d7d5c250076c
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 11 23:44:16 2017 +0000
+Date: Sat Jun 24 05:24:11 2017 +0000
upstream commit
- regress tests for loading certificates without public keys;
- bz#2617 based on patch from Adam Eijdenberg; ok markus@ dtucker@
+ no need to call log_init to reinitialise logged PID in
+ child sessions, since we haven't called openlog() in log_init() since 1999;
+ ok markus@
- Upstream-Regress-ID: 0145d19328ed995b73fe2d9da33596b17429d0d0
+ Upstream-ID: 0906e4002af5d83d3d544df75e1187c932a3cf2e
-commit 1e24552716194db8f2f620587b876158a9ef56ad
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sat Mar 11 23:40:26 2017 +0000
+commit e238645d789cd7eb47541b66aea2a887ea122c9b
+Author: mestre@openbsd.org <mestre@openbsd.org>
+Date: Fri Jun 23 07:24:48 2017 +0000
upstream commit
- allow ssh to use certificates accompanied by a private
- key file but no corresponding plain *.pub public key. bz#2617 based on patch
- from Adam Eijdenberg; ok dtucker@ markus@
+ When using the escape sequence &~ the code path is
+ client_loop() -> client_simple_escape_filter() -> process_escapes() -> fork()
+ and the pledge for this path lacks the proc promise and therefore aborts the
+ process. The solution is to just add proc the promise to this specific
+ pledge.
+
+ Reported by Gregoire Jadi gjadi ! omecha.info
+ Insight with tb@, OK jca@
- Upstream-ID: 295668dca2c39505281577217583ddd2bd4b00b9
+ Upstream-ID: 63c05e30c28209519f476023b65b0b1b0387a05b
-commit 0fb1a617a07b8df5de188dd5a0c8bf293d4bfc0e
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Sat Mar 11 13:07:35 2017 +0000
+commit 5abbb31c4e7a6caa922cc1cbb14e87a77f9d19d3
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Fri Jun 23 03:30:42 2017 +0000
upstream commit
- Don't count the initial block twice when computing how
- many bytes to discard for the work around for the attacks against CBC-mode.
- ok djm@; report from Jean Paul, Kenny, Martin and Torben @ RHUL
+ Import regenerated moduli.
- Upstream-ID: f445f509a4e0a7ba3b9c0dae7311cb42458dc1e2
+ Upstream-ID: b25bf747544265b39af74fe0716dc8d9f5b63b95
-commit ef653dd5bd5777132d9f9ee356225f9ee3379504
+commit 849c5468b6d9b4365784c5dd88e3f1fb568ba38f
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 07:18:32 2017 +0000
+Date: Fri Jun 23 03:25:53 2017 +0000
upstream commit
- krl.c
+ Run the screen twice so we end up with more candidate
+ groups. ok djm@
- Upstream-ID: fc5e695d5d107d730182e2da7b23f00b489e0ee1
+ Upstream-ID: b92c93266d8234d493857bb822260dacf4366157
-commit d94c1dfef2ea30ca67b1204ada7c3b537c54f4d0
-Author: Damien Miller <djm@mindrot.org>
-Date: Sun Mar 12 10:48:14 2017 +1100
+commit 4626e39c7053c6486c1c8b708ec757e464623f5f
+Author: dtucker@openbsd.org <dtucker@openbsd.org>
+Date: Wed Jun 14 00:31:38 2017 +0000
- sync fmt_scaled.c with OpenBSD
+ upstream commit
- revision 1.13
- date: 2017/03/11 23:37:23; author: djm; state: Exp; lines: +14 -1; commitid: jnFKyHkB3CEiEZ2R;
- fix signed integer overflow in scan_scaled. Found by Nicolas Iooss
- using AFL against ssh_config. ok deraadt@ millert@
- ----------------------------
- revision 1.12
- date: 2013/11/29 19:00:51; author: deraadt; state: Exp; lines: +6 -5;
- fairly simple unsigned char casts for ctype
- ok krw
- ----------------------------
- revision 1.11
- date: 2012/11/12 14:07:20; author: halex; state: Exp; lines: +4 -2;
- make scan_scaled set errno to EINVAL rather than ERANGE if it encounters
- an invalid multiplier, like the man page says it should
+ Add user@host prefix to client's "Permisison denied"
+ messages, useful in particular when using "stacked" connections where it's
+ not clear which host is denying. bz#2720, ok djm@ markus@
- "looks sensible" deraadt@, ok ian@
- ----------------------------
- revision 1.10
- date: 2009/06/20 15:00:04; author: martynas; state: Exp; lines: +4 -4;
- use llabs instead of the home-grown version; and some comment changes
- ok ian@, millert@
- ----------------------------
+ Upstream-ID: de88e1e9dcb050c98e85377482d1287a9fe0d2be
-commit 894221a63fa061e52e414ca58d47edc5fe645968
+commit c948030d54911b2d3cddb96a7a8e9269e15d11cd
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 05:01:13 2017 +0000
+Date: Tue Jun 13 12:13:59 2017 +0000
upstream commit
- When updating hostkeys, accept RSA keys if
- HostkeyAlgorithms contains any RSA keytype. Previously, ssh could ignore RSA
- keys when any of the ssh-rsa-sha2-* methods was enabled in HostkeyAlgorithms
- nit ssh-rsa (SHA1 signatures) was not. bz#2650 reported by Luis Ressel; ok
- dtucker@
+ Do not require that unknown EXT_INFO extension values not
+ contain \0 characters. This would cause fatal connection errors if an
+ implementation sent e.g. string-encoded sub-values inside a value.
+
+ Reported by Denis Bider; ok markus@
- Upstream-ID: c5e8cfee15c42f4a05d126158a0766ea06da79d2
+ Upstream-ID: 030e10fdc605563c040244c4b4f1d8ae75811a5c
-commit dd3e2298663f4cc1a06bc69582d00dcfee27d73c
+commit 6026f48dfca78b713e4a7f681ffa42a0afe0929e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 04:24:55 2017 +0000
+Date: Tue Jun 13 11:22:15 2017 +0000
upstream commit
- make hostname matching really insensitive to case;
- bz#2685, reported by Petr Cerny; ok dtucker@
+ missing prototype.
- Upstream-ID: e467622ff154269e36ba8b6c9e3d105e1c4a9253
+ Upstream-ID: f443d2be9910fd2165a0667956d03343c46f66c9
-commit 77a9be9446697fe8b5499fe651f4a82a71a4b51f
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 03:52:48 2017 +0000
+commit bcd1485075aa72ba9418003f5cc27af2b049c51b
+Author: Damien Miller <djm@mindrot.org>
+Date: Sat Jun 10 23:41:25 2017 +1000
- upstream commit
-
- reword a comment to make it fit 80 columns
+ portability for sftp globbed ls sort by mtime
- Upstream-ID: 4ef509a66b96c7314bbcc87027c2af71fa9d0ba4
+ Include replacement timespeccmp() for systems that lack it.
+ Support time_t struct stat->st_mtime in addition to
+ timespec stat->st_mtim, as well as unsorted fallback.
-commit 61b8ef6a66efaec07e023342cb94a10bdc2254dc
+commit 072e172f1d302d2a2c6043ecbfb4004406717b96
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 04:27:32 2017 +0000
+Date: Sat Jun 10 06:36:46 2017 +0000
upstream commit
- better match sshd config parser behaviour: fatal() if
- line is overlong, increase line buffer to match sshd's; bz#2651 reported by
- Don Fong; ok dtucker@
+ print '?' instead of incorrect link count (that the
+ protocol doesn't provide) for remote listings. bz#2710 ok dtucker@
- Upstream-ID: b175ae7e0ba403833f1ee566edf10f67443ccd18
+ Upstream-ID: c611f98a66302cea452ef10f13fff8cf0385242e
-commit db2597207e69912f2592cd86a1de8e948a9d7ffb
+commit 72be5b2f8e7dc37235e8c4b8d0bc7b5ee1301505
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 04:26:06 2017 +0000
+Date: Sat Jun 10 06:33:34 2017 +0000
upstream commit
- ensure hostname is lower-case before hashing it;
- bz#2591 reported by Griff Miller II; ok dtucker@
+ implement sorting for globbed ls; bz#2649 ok dtucker@
- Upstream-ID: c3b8b93804f376bd00d859b8bcd9fc0d86b4db17
+ Upstream-ID: ed3110f351cc9703411bf847ba864041fb7216a8
-commit df9936936c695f85c1038bd706d62edf752aca4b
+commit 5b2f34a74aa6a524cd57e856b23e1b7b25007721
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 04:24:55 2017 +0000
+Date: Fri Jun 9 06:47:13 2017 +0000
upstream commit
- make hostname matching really insensitive to case;
- bz#2685, reported by Petr Cerny; ok dtucker@
+ return failure rather than fatal() for more cases during
+ mux negotiations. Causes the session to fall back to a non-mux connection if
+ they occur. bz#2707 ok dtucker@
- Upstream-ID: e632b7a9bf0d0558d5ff56dab98b7cca6c3db549
+ Upstream-ID: d2a7892f464d434e1f615334a1c9d0cdb83b29ab
-commit 67eed24bfa7645d88fa0b883745fccb22a0e527e
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 04:11:00 2017 +0000
+commit 7f5637c4a67a49ef256cb4eedf14e8590ac30976
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 9 06:43:01 2017 +0000
upstream commit
- Remove old null check from config dumper. Patch from
- jjelen at redhat.com vi bz#2687, ok djm@
+ in description of public key authentication, mention that
+ the server will send debug messages to the client for some error conditions
+ after authentication has completed. bz#2709 ok dtucker
- Upstream-ID: 824ab71467b78c4bab0dd1b3a38e8bc5f63dd528
+ Upstream-ID: 750127dbd58c5a2672c2d28bc35fe221fcc8d1dd
-commit 183ba55aaaecca0206184b854ad6155df237adbe
+commit 2076e4adb986512ce8c415dd194fd4e52136c4b4
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 04:07:20 2017 +0000
+Date: Fri Jun 9 06:40:24 2017 +0000
upstream commit
- fix regression in 7.4 server-sig-algs, where we were
- accidentally excluding SHA2 RSA signature methods. bz#2680, patch from Nuno
- Goncalves; ok dtucker@
+ better translate libcrypto errors by looking deeper in
+ the accursed error stack for codes that indicate the wrong passphrase was
+ supplied for a PEM key. bz#2699 ok dtucker@
- Upstream-ID: 81ac8bfb30960447740b9b8f6a214dcf322f12e8
+ Upstream-ID: 4da4286326d570f4f0489459bb71f6297e54b681
-commit 66be4fe8c4435af5bbc82998501a142a831f1181
+commit ad0531614cbe8ec424af3c0fa90c34a8e1ebee4c
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 03:53:11 2017 +0000
+Date: Fri Jun 9 04:40:04 2017 +0000
upstream commit
- Check for NULL return value from key_new. Patch from
- jjelen at redhat.com via bz#2687, ok djm@
+ Add comments referring to the relevant RFC sections for
+ rekeying behaviour.
- Upstream-ID: 059e33cd43cba88dc8caf0b1936fd4dd88fd5b8e
+ Upstream-ID: 6fc8e82485757a27633f9175ad00468f49a07d40
-commit ec2892b5c7fea199914cb3a6afb3af38f84990bf
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 03:52:48 2017 +0000
+commit ce9134260b9b1247e2385a1afed00c26112ba479
+Author: Damien Miller <djm@mindrot.org>
+Date: Fri Jun 9 14:43:47 2017 +1000
- upstream commit
-
- reword a comment to make it fit 80 columns
+ drop two more privileges in the Solaris sandbox
- Upstream-ID: b4b48b4487c0821d16e812c40c9b09f03b28e349
+ Drop PRIV_DAX_ACCESS and PRIV_SYS_IB_INFO.
+ Patch from huieying.lee AT oracle.com via bz#2723
-commit 7fadbb6da3f4122de689165651eb39985e1cba85
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 03:48:57 2017 +0000
+commit e0f609c8a2ab940374689ab8c854199c3c285a76
+Author: Darren Tucker <dtucker@zip.com.au>
+Date: Fri Jun 9 13:36:29 2017 +1000
- upstream commit
-
- Check for NULL argument to sshkey_read. Patch from
- jjelen at redhat.com via bz#2687, ok djm@
-
- Upstream-ID: c2d00c2ea50c4861d271d0a586f925cc64a87e0e
+ Wrap stdint.h include in #ifdef.
-commit 5a06b9e019e2b0b0f65a223422935b66f3749de3
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 03:45:40 2017 +0000
+commit 1de5e47a85850526a4fdaf77185134046c050f75
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed Jun 7 01:48:15 2017 +0000
upstream commit
- Plug some mem leaks mostly on error paths. From jjelen
- at redhat.com via bz#2687, ok djm@
+ unbreak after sshv1 purge
- Upstream-ID: 3fb030149598957a51b7c8beb32bf92cf30c96f2
+ Upstream-Regress-ID: 8ea01a92d5f571b9fba88c1463a4254a7552d51b
-commit f6edbe9febff8121f26835996b1229b5064d31b7
+commit 550c053168123fcc0791f9952abad684704b5760
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 03:24:48 2017 +0000
+Date: Tue Jun 6 09:12:17 2017 +0000
upstream commit
- Plug mem leak on GLOB_NOMATCH case. From jjelen at
- redhat.com via bz#2687, ok djm@
+ Fix compression output stats broken in rev 1.201. Patch
+ originally by Russell Coker via Debian bug #797964 and Christoph Biedl. ok
+ djm@
- Upstream-ID: 8016a7ae97719d3aa55fb723fc2ad3200058340d
+ Upstream-ID: 83a1903b95ec2e4ed100703debb4b4a313b01016
-commit 566b3a46e89a2fda2db46f04f2639e92da64a120
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 03:22:40 2017 +0000
+commit 55d06c6e72a9abf1c06a7ac2749ba733134a1f39
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Jun 2 06:06:10 2017 +0000
upstream commit
- Plug descriptor leaks of auth_sock. From jjelen at
- redhat.com via bz#2687, ok djm@
+ rationalise the long list of manual CDIAGFLAGS that we
+ add; most of these were redundant to -Wall -Wextra
- Upstream-ID: 248acb99a5ed2fdca37d1aa33c0fcee7be286d88
+ Upstream-ID: ea80f445e819719ccdcb237022cacfac990fdc5c
-commit 8a2834454c73dfc1eb96453c0e97690595f3f4c2
+commit 1527d9f61e6d50f6c2b4a3fa5b45829034b1b0b1
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 03:18:24 2017 +0000
+Date: Thu Jun 1 06:59:21 2017 +0000
upstream commit
- correctly hash hosts with a port number. Reported by Josh
- Powers in bz#2692; ok dtucker@
+ no need to bzero allocated space now that we use use
+ recallocarray; ok deraadt@
- Upstream-ID: 468e357ff143e00acc05bdd2803a696b3d4b6442
+ Upstream-ID: 53333c62ccf97de60b8cb570608c1ba5ca5803c8
-commit 9747b9c742de409633d4753bf1a752cbd211e2d3
+commit cc812baf39b93d5355565da98648d8c31f955990
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 10 03:15:58 2017 +0000
+Date: Thu Jun 1 06:58:25 2017 +0000
upstream commit
- don't truncate off \r\n from long stderr lines; bz#2688,
- reported by Brian Dyson; ok dtucker@
+ unconditionally zero init size of buffer; ok markus@
+ deraadt@
- Upstream-ID: cdfdc4ba90639af807397ce996153c88af046ca4
+ Upstream-ID: 218963e846d8f26763ba25afe79294547b99da29
+
+commit 65eb8fae0d7ba45ef4483a3cf0ae7fd0dbc7c226
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Jun 1 16:25:09 2017 +1000
+
+ avoid compiler warning
-commit 4a4b75adac862029a1064577eb5af299b1580cdd
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Mar 10 02:59:51 2017 +0000
+commit 2d75d74272dc2a0521fce13cfe6388800c9a2406
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Thu Jun 1 06:16:43 2017 +0000
upstream commit
- Validate digest arg in ssh_digest_final; from jjelen at
- redhat.com via bz#2687, ok djm@
+ some warnings spotted by clang; ok markus@
- Upstream-ID: dbe5494dfddfe523fab341a3dab5a79e7338f878
+ Upstream-ID: 24381d68ca249c5cee4388ceb0f383fa5b43991b
-commit bee0167be2340d8de4bdc1ab1064ec957c85a447
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Mar 10 13:40:18 2017 +1100
+commit 151c6e433a5f5af761c78de87d7b5d30a453cf5e
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Jun 1 15:25:13 2017 +1000
- Check for NULL from malloc.
+ add recallocarray replacement and dependency
- Part of bz#2687, from jjelen at redhat.com.
+ recallocarray() needs getpagesize() so add a tiny replacement for that.
-commit da39b09d43b137a5a3d071b51589e3efb3701238
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Mar 10 13:22:32 2017 +1100
+commit 01e6f78924da308447e71e9a32c8a6104ef4e888
+Author: Damien Miller <djm@mindrot.org>
+Date: Thu Jun 1 15:16:24 2017 +1000
- If OSX is using launchd, remove screen no.
-
- Check for socket with and without screen number. From Apple and Jakob
- Schlyter via bz#2341, with contributions from Ron Frederick, ok djm@
+ add *.0 manpage droppings
-commit 8fb15311a011517eb2394bb95a467c209b8b336c
+commit 4b2e2d3fd9dccff357e1e26ce9a5f2e103837a36
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Mar 8 12:07:47 2017 +0000
+Date: Thu Jun 1 04:51:58 2017 +0000
upstream commit
- quote [host]:port in generated ProxyJump commandline; the
- [ / ] characters can confuse some shells (e.g. zsh). Reported by Lauri
- Tirkkonen via bugs@
+ fix casts re constness
- Upstream-ID: 65cdd161460e1351c3d778e974c1c2a4fa4bc182
+ Upstream-ID: e38f2bac162b37dbaf784d349c8327a6626fa266
-commit 18501151cf272a15b5f2c5e777f2e0933633c513
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Mar 6 02:03:20 2017 +0000
+commit 75b8af8de805c0694b37fcf80ce82783b2acc86f
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed May 31 10:54:00 2017 +0000
upstream commit
- Check l->hosts before dereferencing; fixes potential null
- pointer deref. ok djm@
+ make sure we don't pass a NULL string to vfprintf
+ (triggered by the principals-command regress test); ok bluhm
- Upstream-ID: 81c0327c6ec361da794b5c680601195cc23d1301
+ Upstream-ID: eb49854f274ab37a0b57056a6af379a0b7111990
-commit d072370793f1a20f01ad827ba8fcd3b8f2c46165
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Mar 6 00:44:51 2017 +0000
+commit 84008608c9ee944d9f72f5100f31ccff743b10f2
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed May 31 10:04:29 2017 +0000
upstream commit
- linenum is unsigned long so use %lu in log formats. ok
- deraadt@
+ use SO_ZEROIZE for privsep communication (if available)
- Upstream-ID: 9dc582d9bb887ebe0164e030d619fc20b1a4ea08
+ Upstream-ID: abcbb6d2f8039fc4367a6a78096e5d5c39de4a62
-commit 12d3767ba4c84c32150cbe6ff6494498780f12c9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Mar 3 06:13:11 2017 +0000
+commit 9e509d4ec97cb3d71696f1a2f1fdad254cbbce11
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Wed May 31 09:15:42 2017 +0000
upstream commit
- fix ssh-keygen -H accidentally corrupting known_hosts that
- contained already-hashed entries. HKF_MATCH_HOST_HASHED is only set by
- hostkeys_foreach() when hostname matching is in use, so we need to look for
- the hash marker explicitly.
+ Switch to recallocarray() for a few operations. Both
+ growth and shrinkage are handled safely, and there also is no need for
+ preallocation dances. Future changes in this area will be less error prone.
+ Review and one bug found by markus
- Upstream-ID: da82ad653b93e8a753580d3cf5cd448bc2520528
+ Upstream-ID: 822d664d6a5a1d10eccb23acdd53578a679d5065
-commit d7abb771bd5a941b26144ba400a34563a1afa589
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Feb 28 06:10:08 2017 +0000
+commit dc5dc45662773c0f7745c29cf77ae2d52723e55e
+Author: deraadt@openbsd.org <deraadt@openbsd.org>
+Date: Wed May 31 08:58:52 2017 +0000
upstream commit
- small memleak: free fd_set on connection timeout (though
- we are heading to exit anyway). From Tom Rix in bz#2683
+ These shutdown() SHUT_RDWR are not needed before close()
+ ok djm markus claudio
- Upstream-ID: 10e3dadbb8199845b66581473711642d9e6741c4
+ Upstream-ID: 36f13ae4ba10f5618cb9347933101eb4a98dbcb5
-commit 78142e3ab3887e53a968d6e199bcb18daaf2436e
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Mon Feb 27 14:30:33 2017 +0000
+commit 1e0cdf8efb745d0d1116e1aa22bdc99ee731695e
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed May 31 08:09:45 2017 +0000
upstream commit
- errant dot; from klemens nanni
+ clear session keys from memory; ok djm@
- Upstream-ID: 83d93366a5acf47047298c5d3ebc5e7426f37921
+ Upstream-ID: ecd178819868975affd5fd6637458b7c712b6a0f
-commit 8071a6924c12bb51406a9a64a4b2892675112c87
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 24 03:16:34 2017 +0000
+commit 92e9fe633130376a95dd533df6e5e6a578c1e6b8
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed May 31 07:00:13 2017 +0000
upstream commit
- might as well set the listener socket CLOEXEC
+ remove now obsolete ctx from ssh_dispatch_run; ok djm@
- Upstream-ID: 9c538433d6a0ca79f5f21decc5620e46fb68ab57
+ Upstream-ID: 9870aabf7f4d71660c31fda91b942b19a8e68d29
-commit d5499190559ebe374bcdfa8805408646ceffad64
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Feb 19 00:11:29 2017 +0000
+commit 17ad5b346043c5bbc5befa864d0dbeb76be39390
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Wed May 31 05:34:14 2017 +0000
upstream commit
- add test cases for C locale; ok schwarze@
+ use the ssh_dispatch_run_fatal variant
- Upstream-Regress-ID: 783d75de35fbc923d46e2a5e6cee30f8f381ba87
+ Upstream-ID: 28c5b364e37c755d1b22652b8cd6735a05c625d8
-commit 011c8ffbb0275281a0cf330054cf21be10c43e37
+commit 39896b777320a6574dd06707aebac5fb98e666da
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Feb 19 00:10:57 2017 +0000
+Date: Wed May 31 05:08:46 2017 +0000
upstream commit
- Add a common nl_langinfo(CODESET) alias for US-ASCII
- "ANSI_X3.4-1968" that is used by Linux. Fixes mprintf output truncation for
- non-UTF-8 locales on Linux spotted by dtucker@; ok deraadt@ schwarze@
+ another ctx => ssh conversion (in GSSAPI code)
- Upstream-ID: c6808956ebffd64066f9075d839f74ff0dd60719
+ Upstream-ID: 4d6574c3948075c60608d8e045af42fe5b5d8ae0
-commit 0c4430a19b73058a569573492f55e4c9eeaae67b
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Feb 7 23:03:11 2017 +0000
+commit 6116bd4ed354a71a733c8fd0f0467ce612f12911
+Author: Damien Miller <djm@mindrot.org>
+Date: Wed May 31 14:56:07 2017 +1000
- upstream commit
-
- Remove deprecated SSH1 options RSAAuthentication and
- RhostsRSAAuthentication from regression test sshd_config.
+ fix conversion of kexc25519s.c to struct ssh too
- Upstream-Regress-ID: 8066b753d9dce7cf02ff87af5c727ff680d99491
+ git cvsimport missed this commit for some reason
-commit 3baa4cdd197c95d972ec3d07f1c0d08f2d7d9199
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 17 02:32:05 2017 +0000
+commit d40dbdc85b6fb2fd78485ba02225511b8cbf20d7
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed May 31 04:29:44 2017 +0000
upstream commit
- Do not show rsa1 key type in usage when compiled without
- SSH1 support.
+ spell out that custom options/extensions should follow the
+ usual SSH naming rules, e.g. "extension@example.com"
- Upstream-ID: 068b5c41357a02f319957746fa4e84ea73960f57
+ Upstream-ID: ab326666d2fad40769ec96b5a6de4015ffd97b8d
-commit ecc35893715f969e98fee118481f404772de4132
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 17 02:31:14 2017 +0000
+commit 2a108277f976e8d0955c8b29d1dfde04dcbb3d5b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Wed May 31 04:17:12 2017 +0000
upstream commit
- ifdef out "rsa1" from the list of supported keytypes when
- compiled without SSH1 support. Found by kdunlop at guralp.com, ok djm@
+ one more void *ctx => struct ssh *ssh conversion
- Upstream-ID: cea93a26433d235bb1d64b1d990f19a9c160a70f
+ Upstream-ID: d299d043471c10214cf52c03daa10f1c232759e2
-commit 10577c6d96a55b877a960b2d0b75edef1b9945af
+commit c04e979503e97f52b750d3b98caa6fe004ab2ab9
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 17 02:04:15 2017 +0000
+Date: Wed May 31 00:43:04 2017 +0000
upstream commit
- For ProxyJump/-J, surround host name with brackets to
- allow literal IPv6 addresses. From Dick Visser; ok dtucker@
+ fix possible OOB strlen() in SOCKS4A hostname parsing;
+ ok markus@
- Upstream-ID: 3a5d3b0171250daf6a5235e91bce09c1d5746bf1
+ Upstream-ID: c67297cbeb0e5a19d81752aa18ec44d31270cd11
-commit b2afdaf1b52231aa23d2153f4a8c5a60a694dda4
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Wed Feb 15 23:38:31 2017 +0000
+commit a3bb250c93bfe556838c46ed965066afce61cffa
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 30 19:38:17 2017 +0000
upstream commit
- Fix memory leaks in match_filter_list() error paths.
-
- ok dtucker@ markus@
+ tweak previous;
- Upstream-ID: c7f96ac0877f6dc9188bbc908100a8d246cc7f0e
+ Upstream-ID: 66987651046c42d142f7318c9695fb81a6d14031
-commit 6d5a41b38b55258213ecfaae9df7a758caa752a1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Feb 15 01:46:47 2017 +0000
+commit 1112b534a6a7a07190e497e6bf86b0d5c5fb02dc
+Author: bluhm@openbsd.org <bluhm@openbsd.org>
+Date: Tue May 30 18:58:37 2017 +0000
upstream commit
- fix division by zero crash in "df" output when server
- returns zero total filesystem blocks/inodes. Spotted by Guido Vranken; ok
- dtucker@
-
- Upstream-ID: 6fb6c2ae6b289aa07b6232dbc0be54682ef5419f
-
-commit bd5d7d239525d595ecea92765334af33a45d9d63
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Sun Feb 12 15:45:15 2017 +1100
-
- ifdef out EVP_R_PRIVATE_KEY_DECODE_ERROR
+ Add RemoteCommand option to specify a command in the
+ ssh config file instead of giving it on the client's command line. This
+ command will be executed on the remote host. The feature allows to automate
+ tasks using ssh config. OK markus@
- EVP_R_PRIVATE_KEY_DECODE_ERROR was added in OpenSSL 1.0.0 so ifdef out
- for the benefit of OpenSSL versions prior to that.
+ Upstream-ID: 5d982fc17adea373a9c68cae1021ce0a0904a5ee
-commit 155d540d00ff55f063421ec182ec8ff2b7ab6cbe
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 10 04:34:50 2017 +0000
+commit eb272ea4099fd6157846f15c129ac5727933aa69
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:29:59 2017 +0000
upstream commit
- bring back r1.34 that was backed out for problems loading
- public keys:
-
- translate OpenSSL error codes to something more
- meaninful; bz#2522 reported by Jakub Jelen, ok dtucker@
-
- with additional fix from Jakub Jelen to solve the backout.
- bz#2525 bz#2523 re-ok dtucker@
+ switch auth2 to ssh_dispatch API; ok djm@
- Upstream-ID: a9d5bc0306f4473d9b4f4484f880e95f3c1cc031
+ Upstream-ID: a752ca19e2782900dd83060b5c6344008106215f
-commit a287c5ad1e0bf9811c7b9221979b969255076019
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 10 03:36:40 2017 +0000
+commit 5a146bbd4fdf5c571f9fb438e5210d28cead76d9
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:27:22 2017 +0000
upstream commit
- Sanitise escape sequences in key comments sent to printf
- but preserve valid UTF-8 when the locale supports it; bz#2520 ok dtucker@
+ switch auth2-none.c to modern APIs; ok djm@
- Upstream-ID: e8eed28712ba7b22d49be534237eed019875bd1e
+ Upstream-ID: 07252b58e064d332214bcabbeae8e08c44b2001b
-commit e40269be388972848aafcca7060111c70aab5b87
-Author: millert@openbsd.org <millert@openbsd.org>
-Date: Wed Feb 8 20:32:43 2017 +0000
+commit 60306b2d2f029f91927c6aa7c8e08068519a0fa2
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:26:49 2017 +0000
upstream commit
- Avoid printf %s NULL. From semarie@, OK djm@
+ switch auth2-passwd.c to modern APIs; ok djm@
- Upstream-ID: 06beef7344da0208efa9275d504d60d2a5b9266c
+ Upstream-ID: cba0a8b72b4f97adfb7e3b3fd2f8ba3159981fc7
-commit 5b90709ab8704dafdb31e5651073b259d98352bc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Feb 6 09:22:51 2017 +0000
+commit eb76698b91338bd798c978d4db2d6af624d185e4
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:25:42 2017 +0000
upstream commit
- Restore \r\n newline sequence for server ident string. The CR
- got lost in the flensing of SSHv1. Pointed out by Stef Bon
+ switch auth2-hostbased.c to modern APIs; ok djm@
- Upstream-ID: 5333fd43ce5396bf5999496096fac5536e678fac
+ Upstream-ID: 146af25c36daeeb83d5dbbb8ca52b5d25de88f4e
-commit 97c31c46ee2e6b46dfffdfc4f90bbbf188064cbc
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 3 23:01:42 2017 +0000
+commit 2ae666a8fc20b3b871b2f1b90ad65cc027336ccd
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:23:52 2017 +0000
upstream commit
- unit test for match_filter_list() function; still want a
- better name for this...
+ protocol handlers all get struct ssh passed; ok djm@
- Upstream-Regress-ID: 840ad6118552c35111f0a897af9c8d93ab8de92a
+ Upstream-ID: 0ca9ea2a5d01a6d2ded94c5024456a930c5bfb5d
-commit f1a193464a7b77646f0d0cedc929068e4a413ab4
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 3 23:05:57 2017 +0000
+commit 94583beb24a6c5fd19cedb9104ab2d2d5cd052b6
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:19:15 2017 +0000
upstream commit
- use ssh_packet_set_log_preamble() to include connection
- username in packet log messages, e.g.
-
- Connection closed by invalid user foo 10.1.1.1 port 44056 [preauth]
-
- ok markus@ bz#113
+ ssh: pass struct ssh to auth functions, too; ok djm@
- Upstream-ID: 3591b88bdb5416d6066fb3d49d8fff2375bf1a15
+ Upstream-ID: d13c509cc782f8f19728fbea47ac7cf36f6e85dd
-commit 07edd7e9537ab32aa52abb5fb2a915c350fcf441
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 3 23:03:33 2017 +0000
+commit 5f4082d886c6173b9e90b9768c9a38a3bfd92c2b
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:18:15 2017 +0000
upstream commit
- add ssh_packet_set_log_preamble() to allow inclusion of a
- preamble string in disconnect messages; ok markus@
+ sshd: pass struct ssh to auth functions; ok djm@
- Upstream-ID: 34cb41182cd76d414c214ccb01c01707849afead
+ Upstream-ID: b00a80c3460884ebcdd14ef550154c761aebe488
-commit 68bc8cfa7642d3ccbf2cd64281c16b8b9205be59
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 3 23:01:19 2017 +0000
+commit 7da5df11ac788bc1133d8d598d298e33500524cc
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:16:41 2017 +0000
upstream commit
- support =- for removing methods from algorithms lists,
- e.g. Ciphers=-*cbc; suggested by Cristian Ionescu-Idbohrn in bz#2671 "I like
- it" markus@
+ remove unused wrapper functions from key.[ch]; ok djm@
- Upstream-ID: c78c38f9f81a963b33d0eade559f6048add24a6d
+ Upstream-ID: ea0f4016666a6817fc11f439dd4be06bab69707e
-commit c924b2ef941028a1f31e6e94f54dfeeeef462a4e
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Feb 3 05:05:56 2017 +0000
+commit ff7371afd08ac0bbd957d90451d4dcd0da087ef5
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:15:17 2017 +0000
upstream commit
- allow form-feed characters at EOL; bz#2431 ok dtucker@
+ sshkey_new() might return NULL (pkcs#11 code only); ok
+ djm@
- Upstream-ID: 1f453afaba6da2ae69d6afdf1ae79a917552f1a2
+ Upstream-ID: de9f2ad4a42c0b430caaa7d08dea7bac943075dd
-commit 523db8540b720c4d21ab0ff6f928476c70c38aab
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Feb 3 16:01:22 2017 +1100
+commit beb965bbc5a984fa69fb1e2b45ebe766ae09d1ef
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:13:40 2017 +0000
- prefer to use ldns-config to find libldns
+ upstream commit
- Should fix bz#2603 - "Build with ldns and without kerberos support
- fails if ldns compiled with kerberos support" by including correct
- cflags/libs
+ switch sshconnect.c to modern APIs; ok djm@
- ok dtucker@
+ Upstream-ID: 27be17f84b950d5e139b7a9b281aa487187945ad
-commit c998bf0afa1a01257a53793eba57941182e9e0b7
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Feb 3 02:56:00 2017 +0000
+commit 00ed75c92d1f95fe50032835106c368fa22f0f02
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 14:10:53 2017 +0000
upstream commit
- Make ssh_packet_set_rekey_limits take u32 for the number of
- seconds until rekeying (negative values are rejected at config parse time).
- This allows the removal of some casts and a signed vs unsigned comparison
- warning.
-
- rekey_time is cast to int64 for the comparison which is a no-op
- on OpenBSD, but should also do the right thing in -portable on
- anything still using 32bit time_t (until the system time actually
- wraps, anyway).
-
- some early guidance deraadt@, ok djm@
+ switch auth2-pubkey.c to modern APIs; with & ok djm@
- Upstream-ID: c9f18613afb994a07e7622eb326f49de3d123b6c
+ Upstream-ID: 8f08d4316eb1b0c4ffe4a206c05cdd45ed1daf07
-commit 3ec5fa4ba97d4c4853620daea26a33b9f1fe3422
-Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Thu Feb 2 10:54:25 2017 +0000
+commit 54d90ace1d3535b44d92a8611952dc109a74a031
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 08:52:19 2017 +0000
upstream commit
- In vasnmprintf() return an error if malloc fails and
- don't set a function argument to the address of free'd memory.
-
- ok djm@
+ switch from Key typedef with struct sshkey; ok djm@
- Upstream-ID: 1efffffff2f51d53c9141f245b90ac23d33b9779
+ Upstream-ID: 3067d33e04efbe5131ce8f70668c47a58e5b7a1f
-commit 858252fb1d451ebb0969cf9749116c8f0ee42753
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Feb 1 02:59:09 2017 +0000
+commit c221219b1fbee47028dcaf66613f4f8d6b7640e9
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 08:49:58 2017 +0000
upstream commit
- Return true reason for port forwarding failures where
- feasible rather than always "administratively prohibited". bz#2674, ok djm@
+ remove ssh1 references; ok djm@
- Upstream-ID: d901d9887951774e604ca970e1827afaaef9e419
+ Upstream-ID: fc23b7578e7b0a8daaec72946d7f5e58ffff5a3d
-commit 6ba9f893838489add6ec4213c7a997b425e4a9e0
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Jan 30 23:27:39 2017 +0000
+commit afbfa68fa18081ef05a9cd294958509a5d3cda8b
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Tue May 30 08:49:32 2017 +0000
upstream commit
- Small correction to the known_hosts section on when it is
- updated. Patch from lkppo at free.fr some time ago, pointed out by smallm at
- sdf.org
+ revise sshkey_load_public(): remove ssh1 related
+ comments, remove extra open()/close() on keyfile, prevent leak of 'pub' if
+ 'keyp' is NULL, replace strlcpy+cat with asprintf; ok djm@
- Upstream-ID: 1834d7af179dea1a12ad2137f84566664af225d5
+ Upstream-ID: 6175e47cab5b4794dcd99c1175549a483ec673ca
-commit c61d5ec3c11e7ff9779b6127421d9f166cf10915
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Feb 3 14:10:34 2017 +1100
+commit 813f55336a24fdfc45e7ed655fccc7d792e8f859
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Fri May 26 20:34:49 2017 +0000
- Remove _XOPEN_SOURCE from wide char detection.
+ upstream commit
- Having _XOPEN_SOURCE unconditionally causes problems on some platforms
- and configurations, notably Solaris 64-bit binaries. It was there for
- the benefit of Linux put the required bits in the *-*linux* section.
+ sshbuf_consume: reset empty buffer; ok djm@
- Patch from yvoinov at gmail.com.
+ Upstream-ID: 0d4583ba57f69e369d38bbd7843d85cac37fa821
-commit f25ee13b3e81fd80efeb871dc150fe49d7fc8afd
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 05:22:14 2017 +0000
+commit 6cf711752cc2a7ffaad1fb4de18cae65715ed8bb
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Fri May 26 19:35:50 2017 +0000
upstream commit
- fully unbreak: some $SSH invocations did not have -F
- specified and could pick up the ~/.ssh/config of the user running the tests
+ remove SSH_CHANNEL_XXX_DRAINING (ssh1 only); ok djm@
- Upstream-Regress-ID: f362d1892c0d3e66212d5d3fc02d915c58ef6b89
+ Upstream-ID: e2e225b6ac67b84dd024f38819afff2554fafe42
-commit 6956e21fb26652887475fe77ea40d2efcf25908b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 04:54:07 2017 +0000
+commit 364f0d5edea27767fb0f915ea7fc61aded88d3e8
+Author: markus@openbsd.org <markus@openbsd.org>
+Date: Fri May 26 19:34:12 2017 +0000
upstream commit
- partially unbreak: was not specifying hostname on some
- $SSH invocations
+ remove channel_input_close_confirmation (ssh1 only); ok
+ djm@
- Upstream-Regress-ID: bc8a5e98e57bad0a92ef4f34ed91c1d18294e2cc
+ Upstream-ID: 8e7c8c38f322d255bb0294a5c0ebef53fdf576f1
-commit 52763dd3fe0a4678dafdf7aeb32286e514130afc
+commit 8ba0fd40082751dbbc23a830433488bbfb1abdca
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 01:03:00 2017 +0000
+Date: Fri May 26 01:40:07 2017 +0000
upstream commit
- revise keys/principals command hang fix (bz#2655) to
- consume entire output, avoiding sending SIGPIPE to subprocesses early; ok
- dtucker@
+ fix references to obsolete v00 cert format; spotted by
+ Jakub Jelen
- Upstream-ID: 7cb04b31a61f8c78c4e48ceededcd2fd5c4ee1bc
+ Upstream-ID: 7600ce193ab8fd19451acfe24fc2eb39d46b2c4f
-commit 381a2615a154a82c4c53b787f4a564ef894fe9ac
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 00:38:50 2017 +0000
+commit dcc714c65cfb81eb6903095b4590719e8690f3da
+Author: Mike Frysinger <vapier@chromium.org>
+Date: Wed May 24 23:21:19 2017 -0400
- upstream commit
-
- small cleanup post SSHv1 removal:
-
- remove SSHv1-isms in commented examples
-
- reorder token table to group deprecated and compile-time conditional tokens
- better
-
- fix config dumping code for some compile-time conditional options that
- weren't being correctly skipped (SSHv1 and PKCS#11)
+ configure: actually set cache vars when cross-compiling
- Upstream-ID: f2e96b3cb3158d857c5a91ad2e15925df3060105
+ The cross-compiling fallback message says it's assuming the test
+ passed, but it didn't actually set the cache var which causes
+ later tests to fail.
-commit 4833d01591b7eb049489d9558b65f5553387ed43
+commit 947a3e829a5b8832a4768fd764283709a4ca7955
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 00:34:01 2017 +0000
+Date: Sat May 20 02:35:47 2017 +0000
upstream commit
- some explicit NULL tests when dumping configured
- forwardings; from Karsten Weiss
+ there's no reason to artificially limit the key path
+ here, just check that it fits PATH_MAX; spotted by Matthew Patton
- Upstream-ID: 40957b8dea69672b0e50df6b4a91a94e3e37f72d
+ Upstream-ID: 858addaf2009c9cf04d80164a41b2088edb30b58
-commit 326e2fae9f2e3e067b5651365eba86b35ee5a6b2
+commit 773224802d7cb250bb8b461546fcce10567b4b2e
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 00:32:28 2017 +0000
+Date: Fri May 19 21:07:17 2017 +0000
upstream commit
- misplaced braces in test; from Karsten Weiss
+ Now that we no longer support SSHv1, replace the contents
+ of this file with a pointer to
+ https://tools.ietf.org/html/draft-miller-ssh-agent-00 It's better edited,
+ doesn't need to document stuff we no longer implement and does document stuff
+ that we do implement (RSA SHA256/512 signature flags)
- Upstream-ID: f7b794074d3aae8e35b69a91d211c599c94afaae
+ Upstream-ID: da8cdc46bbcc266efabd565ddddd0d8e556f846e
-commit 3e032a95e46bfaea9f9e857678ac8fa5f63997fb
+commit 54cd41a4663fad66406dd3c8fe0e4760ccd8a899
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Jan 30 00:32:03 2017 +0000
+Date: Wed May 17 01:24:17 2017 +0000
upstream commit
- don't dereference authctxt before testing != NULL, it
- causes compilers to make assumptions; from Karsten Weiss
+ allow LogLevel in sshd_config Match blocks; ok dtucker
+ bz#2717
- Upstream-ID: 794243aad1e976ebc717885b7a97a25e00c031b2
+ Upstream-ID: 662e303be63148f47db1aa78ab81c5c2e732baa8
-commit 01cfaa2b1cfb84f3cdd32d1bf82b120a8d30e057
+commit 277abcda3f1b08d2376686f0ef20320160d4c8ab
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 6 02:51:16 2017 +0000
+Date: Tue May 16 16:56:15 2017 +0000
upstream commit
- use correct ssh-add program; bz#2654, from Colin Watson
+ remove duplicate check; spotted by Jakub Jelen
- Upstream-Regress-ID: 7042a36e1bdaec6562f6e57e9d047efe9c7a6030
+ Upstream-ID: 30c2996c1767616a8fdc49d4cee088efac69c3b0
-commit e5c7ec67cdc42ae2584085e0fc5cc5ee91133cf5
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jan 6 02:26:10 2017 +0000
+commit adb47ce839c977fa197e770c1be8f852508d65aa
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue May 16 16:54:05 2017 +0000
upstream commit
- Account for timeouts in the integrity tests as failures.
-
- If the first test in a series for a given MAC happens to modify the low
- bytes of a packet length, then ssh will time out and this will be
- interpreted as a test failure. Patch from cjwatson at debian.org via
- bz#2658.
+ mention that Ed25519 keys are valid as CA keys; spotted
+ by Jakub Jelen
- Upstream-Regress-ID: e7467613b0badedaa300bc6fc7495ec2f44e2fb9
+ Upstream-ID: d3f6db58b30418cb1c3058211b893a1ffed3dfd4
-commit dbaf599b61bd6e0f8469363a8c8e7f633b334018
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jan 6 02:09:25 2017 +0000
+commit 6bdf70f01e700348bb4d8c064c31a0ab90896df6
+Author: Damien Miller <djm@mindrot.org>
+Date: Tue May 9 14:35:03 2017 +1000
- upstream commit
-
- Make forwarding test less racy by using unix domain
- sockets instead of TCP ports where possible. Patch from cjwatson at
- debian.org via bz#2659.
-
- Upstream-Regress-ID: 4756375aac5916ef9d25452a1c1d5fa9e90299a9
+ clean up regress files and add a .gitignore
-commit 9390b0031ebd6eb5488d3bc4d4333c528dffc0a6
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Jan 29 21:35:23 2017 +0000
+commit 7bdb2eeb1d3c26acdc409bd94532eefa252e440b
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon May 8 22:57:38 2017 +0000
upstream commit
- Fix typo in ~C error message for bad port forward
- cancellation. bz#2672, from Brad Marshall via Colin Watson and Ubuntu's
- bugtracker.
+ remove hmac-ripemd160; ok dtucker
- Upstream-ID: 0d4a7e5ead6cc59c9a44b4c1e5435ab3aada09af
+ Upstream-ID: 896e737ea0bad6e23327d1c127e02d5e9e9c654d
-commit 4ba15462ca38883b8a61a1eccc093c79462d5414
-Author: guenther@openbsd.org <guenther@openbsd.org>
-Date: Sat Jan 21 11:32:04 2017 +0000
+commit 5f02bb1f99f70bb422be8a5c2b77ef853f1db554
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon May 8 06:11:06 2017 +0000
upstream commit
- The POSIX APIs that that sockaddrs all ignore the s*_len
- field in the incoming socket, so userspace doesn't need to set it unless it
- has its own reasons for tracking the size along with the sockaddr.
-
- ok phessler@ deraadt@ florian@
+ make requesting bad ECDSA bits yield the same error
+ (SSH_ERR_KEY_LENGTH) as the same mistake for RSA/DSA
- Upstream-ID: ca6e49e2f22f2b9e81d6d924b90ecd7e422e7437
+ Upstream-ID: bf40d3fee567c271e33f05ef8e4e0fa0b6f0ece6
-commit a1187bd3ef3e4940af849ca953a1b849dae78445
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Fri Jan 6 16:28:12 2017 +0000
+commit d757a4b633e8874629a1442c7c2e7b1b55d28c19
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon May 8 06:08:42 2017 +0000
upstream commit
- keep the tokens list sorted;
+ fix for new SSH_ERR_KEY_LENGTH error value
- Upstream-ID: b96239dae4fb3aa94146bb381afabcc7740a1638
+ Upstream-Regress-ID: c38a6e6174d4c3feca3518df150d4fbae0dca8dc
-commit b64077f9767634715402014f509e58decf1e140d
+commit 2e58a69508ac49c02d1bb6057300fa6a76db1045
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 6 09:27:52 2017 +0000
+Date: Mon May 8 06:03:39 2017 +0000
upstream commit
- fix previous
+ helps if I commit the correct version of the file. fix
+ missing return statement.
- Upstream-ID: c107d6a69bc22325d79fbf78a2a62e04bcac6895
+ Upstream-ID: c86394a3beeb1ec6611e659bfa830254f325546c
-commit 5e820e9ea2e949aeb93071fe31c80b0c42f2b2de
+commit effaf526bfa57c0ac9056ca236becf52385ce8af
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 6 03:53:58 2017 +0000
+Date: Mon May 8 01:52:49 2017 +0000
upstream commit
- show a useful error message when included config files
- can't be opened; bz#2653, ok dtucker@
+ remove arcfour, blowfish and CAST here too
- Upstream-ID: f598b73b5dfe497344cec9efc9386b4e5a3cb95b
+ Upstream-Regress-ID: c613b3bcbef75df1fe84ca4dc2d3ef253dc5e920
-commit 13bd2e2d622d01dc85d22b94520a5b243d006049
+commit 7461a5bc571696273252df28a1f1578968cae506
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 6 03:45:41 2017 +0000
+Date: Mon May 8 00:21:36 2017 +0000
upstream commit
- sshd_config is documented to set
- GSSAPIStrictAcceptorCheck=yes by default, so actually make it do this.
- bz#2637 ok dtucker
+ I was too aggressive with the scalpel in the last commit;
+ unbreak sshd, spotted quickly by naddy@
- Upstream-ID: 99ef8ac51f17f0f7aec166cb2e34228d4d72a665
+ Upstream-ID: fb7e75d2b2c7e6ca57dee00ca645e322dd49adbf
-commit f89b928534c9e77f608806a217d39a2960cc7fd0
+commit bd636f40911094a39c2920bf87d2ec340533c152
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Jan 6 03:41:58 2017 +0000
+Date: Sun May 7 23:15:59 2017 +0000
upstream commit
- Avoid confusing error message when attempting to use
- ssh-keyscan built without SSH protocol v.1 to scan for v.1 keys; bz#2583
+ Refuse RSA keys <1024 bits in length. Improve reporting
+ for keys that do not meet this requirement. ok markus@
- Upstream-ID: 5d214abd3a21337d67c6dcc5aa6f313298d0d165
+ Upstream-ID: b385e2a7b13b1484792ee681daaf79e1e203df6c
-commit 0999533014784579aa6f01c2d3a06e3e8804b680
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Jan 6 02:34:54 2017 +0000
+commit 70c1218fc45757a030285051eb4d209403f54785
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun May 7 23:13:42 2017 +0000
upstream commit
- Re-add '%k' token for AuthorizedKeysCommand which was
- lost during the re-org in rev 1.235. bz#2656, from jboning at gmail.com.
+ Don't offer CBC ciphers by default in the client. ok
+ markus@
- Upstream-ID: 2884e203c02764d7b3fe7472710d9c24bdc73e38
+ Upstream-ID: 94c9ce8d0d1a085052e11c7f3307950fdc0901ef
-commit 51045869fa084cdd016fdd721ea760417c0a3bf3
+commit acaf34fd823235d549c633c0146ee03ac5956e82
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 4 05:37:40 2017 +0000
+Date: Sun May 7 23:12:57 2017 +0000
upstream commit
- unbreak Unix domain socket forwarding for root; ok
- markus@
-
- Upstream-ID: 6649c76eb7a3fa15409373295ca71badf56920a2
-
-commit 58fca12ba967ea5c768653535604e1522d177e44
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Jan 16 09:08:32 2017 +1100
-
- Remove LOGIN_PROGRAM.
+ As promised in last release announcement: remove
+ support for Blowfish, RC4 and CAST ciphers. ok markus@ deraadt@
- UseLogin is gone, remove leftover. bz#2665, from cjwatson at debian.org
+ Upstream-ID: 21f8facdba3fd8da248df6417000867cec6ba222
-commit b108ce92aae0ca0376dce9513d953be60e449ae1
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Jan 4 02:21:43 2017 +0000
+commit 3e371bd2124427403971db853fb2e36ce789b6fd
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Fri May 5 10:42:49 2017 +0000
upstream commit
- relax PKCS#11 whitelist a bit to allow libexec as well as
- lib directories.
+ more simplification and removal of SSHv1-related code;
+ ok djm@
- Upstream-ID: cf5617958e2e2d39f8285fd3bc63b557da484702
+ Upstream-ID: d2f041aa0b79c0ebd98c68a01e5a0bfab2cf3b55
-commit c7995f296b9222df2846f56ecf61e5ae13d7a53d
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Jan 3 05:46:51 2017 +0000
+commit 2e9c324b3a7f15c092d118c2ac9490939f6228fd
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Fri May 5 10:41:58 2017 +0000
upstream commit
- check number of entries in SSH2_FXP_NAME response; avoids
- unreachable overflow later. Reported by Jann Horn
+ remove superfluous protocol 2 mentions; ok jmc@
- Upstream-ID: b6b2b434a6d6035b1644ca44f24cd8104057420f
+ Upstream-ID: 0aaf7567c9f2e50fac5906b6a500a39c33c4664d
-commit ddd3d34e5c7979ca6f4a3a98a7d219a4ed3d98c2
+commit 744bde79c3361e2153cb395a2ecdcee6c713585d
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 30 22:08:02 2016 +0000
+Date: Thu May 4 06:10:57 2017 +0000
upstream commit
- fix deadlock when keys/principals command produces a lot of
- output and a key is matched early; bz#2655, patch from jboning AT gmail.com
-
- Upstream-ID: e19456429bf99087ea994432c16d00a642060afe
-
-commit 30eee7d1b2fec33c14870cc11910610be5d2aa6f
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Dec 20 12:16:11 2016 +1100
-
- Re-add missing "Prerequisites" header and fix typo
+ since a couple of people have asked, leave a comment
+ explaining why we retain SSH v.1 support in the "delete all keys from agent"
+ path.
- Patch from HARUYAMA Seigo <haruyama at unixuser org>.
+ Upstream-ID: 4b42dcfa339813c15fe9248a2c1b7ed41c21bbb4
-commit c8c60f3663165edd6a52632c6ddbfabfce1ca865
+commit 0c378ff6d98d80bc465a4a6a787670fb9cc701ee
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 19 22:35:23 2016 +0000
+Date: Thu May 4 01:33:21 2017 +0000
upstream commit
- use standard /bin/sh equality test; from Mike Frysinger
+ another tentacle: cipher_set_key_string() was only ever
+ used for SSHv1
- Upstream-Regress-ID: 7b6f0b63525f399844c8ac211003acb8e4b0bec2
-
-commit 4a354fc231174901f2629437c2a6e924a2dd6772
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Dec 19 15:59:26 2016 +1100
-
- crank version numbers for release
+ Upstream-ID: 7fd31eb6c48946f7e7cc12af0699fe8eb637e94a
-commit 5f8d0bb8413d4d909cc7aa3c616fb0538224c3c9
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 19 04:55:51 2016 +0000
+commit 9a82e24b986e3e0dc70849dbb2c19aa6c707b37f
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Wed May 3 21:49:18 2017 +0000
upstream commit
- openssh-7.4
+ restore mistakenly deleted description of the
+ ConnectionAttempts option ok markus@
- Upstream-ID: 1ee404adba6bbe10ae9277cbae3a94abe2867b79
+ Upstream-ID: 943002b1b7c470caea3253ba7b7348c359de0348
-commit 3a8213ea0ed843523e34e55ab9c852332bab4c7b
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Mon Dec 19 04:55:18 2016 +0000
+commit 768405fddf64ff83aa6ef701ebb3c1f82d98a2f3
+Author: naddy@openbsd.org <naddy@openbsd.org>
+Date: Wed May 3 21:08:09 2017 +0000
upstream commit
- remove testcase that depends on exact output and
- behaviour of snprintf(..., "%s", NULL)
+ remove miscellaneous SSH1 leftovers; ok markus@
- Upstream-Regress-ID: cab4288531766bd9593cb556613b91a2eeefb56f
+ Upstream-ID: af23696022ae4d45a1abc2fb8b490d8d9dd63b7c
-commit eae735a82d759054f6ec7b4e887fb7a5692c66d7
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Dec 19 03:32:57 2016 +0000
+commit 1a1b24f8229bf7a21f89df21987433283265527a
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Wed May 3 10:01:44 2017 +0000
upstream commit
- Use LOGNAME to get current user and fall back to whoami if
- not set. Mainly to benefit -portable since some platforms don't have whoami.
+ more protocol 1 bits removed; ok djm
- Upstream-Regress-ID: e3a16b7836a3ae24dc8f8a4e43fdf8127a60bdfa
+ Upstream-ID: b5b977eaf756915acb56aef3604a650e27f7c2b9
-commit 0d2f88428487518eea60602bd593989013831dcf
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Dec 16 03:51:19 2016 +0000
+commit 2b6f799e9b230cf13a7eefc05ecead7d8569d6b5
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Wed May 3 06:32:02 2017 +0000
upstream commit
- Add regression test for AllowUsers and DenyUsers. Patch from
- Zev Weiss <zev at bewilderbeest.net>
+ more protocol 1 stuff to go; ok djm
- Upstream-Regress-ID: 8f1aac24d52728398871dac14ad26ea38b533fb9
+ Upstream-ID: 307a30441d2edda480fd1661d998d36665671e47
-commit 3bc8180a008929f6fe98af4a56fb37d04444b417
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Dec 16 15:02:24 2016 +1100
+commit f10c0d32cde2084d2a0b19bc47d80cb93e85a093
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 2 17:04:09 2017 +0000
- Add missing monitor.h include.
+ upstream commit
- Fixes warning pointed out by Zev Weiss <zev at bewilderbeest.net>
+ rsa1 is no longer valid;
+
+ Upstream-ID: 9953d09ed9841c44b7dcf7019fa874783a709d89
-commit 410681f9015d76cc7b137dd90dac897f673244a0
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 16 02:48:55 2016 +0000
+commit 42b690b4fd0faef78c4d68225948b6e5c46c5163
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 2 14:06:37 2017 +0000
upstream commit
- revert to rev1.2; the new bits in this test depend on changes
- to ssh that aren't yet committed
+ add PubKeyAcceptedKeyTypes to the -o list: scp(1) has
+ it, so i guess this should too;
- Upstream-Regress-ID: 828ffc2c7afcf65d50ff2cf3dfc47a073ad39123
+ Upstream-ID: 7fab32e869ca5831d09ab0c40d210b461d527a2c
-commit 2f2ffa4fbe4b671bbffa0611f15ba44cff64d58e
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Dec 16 01:06:27 2016 +0000
+commit d852603214defd93e054de2877b20cc79c19d0c6
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 2 13:44:51 2017 +0000
upstream commit
- Move the "stop sshd" code into its own helper function.
- Patch from Zev Weiss <zev at bewilderbeest.net>, ok djm@
+ remove now obsolete protocol1 options from the -o
+ lists;
- Upstream-Regress-ID: a113dea77df5bd97fb4633ea31f3d72dbe356329
+ Upstream-ID: 828e478a440bc5f9947672c392420510a362b3dd
-commit e15e7152331e3976b35475fd4e9c72897ad0f074
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 16 01:01:07 2016 +0000
+commit 8b60ce8d8111e604c711c4cdd9579ffe0edced74
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 2 09:05:58 2017 +0000
upstream commit
- regression test for certificates along with private key
- with no public half. bz#2617, mostly from Adam Eijdenberg
+ more -O shuffle; ok djm
- Upstream-Regress-ID: 2e74dc2c726f4dc839609b3ce045466b69f01115
+ Upstream-ID: c239991a3a025cdbb030b73e990188dd9bfbeceb
-commit 9a70ec085faf6e55db311cd1a329f1a35ad2a500
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Dec 15 23:50:37 2016 +0000
+commit 3575f0b12afe6b561681582fd3c34067d1196231
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Tue May 2 08:54:19 2017 +0000
upstream commit
- Use $SUDO to read pidfile in case root's umask is
- restricted. From portable.
+ remove -1 / -2 options; pointed out by jmc@
- Upstream-Regress-ID: f6b1c7ffbc5a0dfb7d430adb2883344899174a98
+ Upstream-ID: 65d2a816000741a95df1c7cfdb5fa8469fcc7daa
-commit fe06b68f824f8f55670442fb31f2c03526dd326c
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Dec 15 21:29:05 2016 +0000
+commit 4f1ca823bad12e4f9614895eefe0d0073b84a28f
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 2 08:06:33 2017 +0000
upstream commit
- Add missing braces in DenyUsers code. Patch from zev at
- bewilderbeest.net, ok deraadt@
+ remove options -12 from usage();
- Upstream-ID: d747ace338dcf943b077925f90f85f789714b54e
+ Upstream-ID: db7ceef25132e63b50ed05289bf447fece1d1270
-commit dcc7d74242a574fd5c4afbb4224795b1644321e7
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Thu Dec 15 21:20:41 2016 +0000
+commit 6b84897f7fd39956b849eac7810319d8a9958568
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Tue May 2 07:13:31 2017 +0000
upstream commit
- Fix text in error message. Patch from zev at
- bewilderbeest.net.
+ tidy up -O somewhat; ok djm
- Upstream-ID: deb0486e175e7282f98f9a15035d76c55c84f7f6
+ Upstream-ID: 804405f716bf7ef15c1f36ab48581ca16aeb4d52
-commit b737e4d7433577403a31cff6614f6a1b0b5e22f4
+commit d1c6b7fdbdfe4a7a37ecd48a97f0796b061c2868
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Dec 14 00:36:34 2016 +0000
+Date: Mon May 1 22:09:48 2017 +0000
upstream commit
- disable Unix-domain socket forwarding when privsep is
- disabled
+ when freeing a bitmap, zero all it bytes; spotted by Ilya
+ Kaliman
- Upstream-ID: ab61516ae0faadad407857808517efa900a0d6d0
+ Upstream-ID: 834ac024f2c82389d6ea6b1c7d6701b3836e28e4
-commit 08a1e7014d65c5b59416a0e138c1f73f417496eb
+commit 0f163983016c2988a92e039d18a7569f9ea8e071
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Dec 9 03:04:29 2016 +0000
+Date: Mon May 1 14:08:26 2017 +0000
upstream commit
- log connections dropped in excess of MaxStartups at
- verbose LogLevel; bz#2613 based on diff from Tomas Kuthan; ok dtucker@
-
- Upstream-ID: 703ae690dbf9b56620a6018f8a3b2389ce76d92b
-
-commit 10e290ec00964b2bf70faab15a10a5574bb80527
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Dec 13 13:51:32 2016 +1100
-
- Get default of TEST_SSH_UTF8 from environment.
-
-commit b9b8ba3f9ed92c6220b58d70d1e6d8aa3eea1104
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Dec 13 12:56:40 2016 +1100
-
- Remove commented-out includes.
+ this one I did forget to "cvs rm"
- These commented-out includes have "Still needed?" comments. Since
- they've been commented out for ~13 years I assert that they're not.
-
-commit 25275f1c9d5f01a0877d39444e8f90521a598ea0
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Dec 13 12:54:23 2016 +1100
-
- Add prototype for strcasestr in compat library.
+ Upstream-ID: 5781670c0578fe89663c9085ed3ba477cf7e7913
-commit afec07732aa2985142f3e0b9a01eb6391f523dec
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Dec 13 10:23:03 2016 +1100
+commit 21ed00a8e26fe8a772bcca782175fafc2b0890ed
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon May 1 09:27:45 2017 +0000
- Add strcasestr to compat library.
+ upstream commit
- Fixes build on (at least) Solaris 10.
-
-commit dda78a03af32e7994f132d923c2046e98b7c56c8
-Author: Damien Miller <djm@mindrot.org>
-Date: Mon Dec 12 13:57:10 2016 +1100
-
- Force Turkish locales back to C/POSIX; bz#2643
+ don't know why cvs didn't exterminate these the first
+ time around, I use rm -f and everuthing...
- Turkish locales are unique in their handling of the letters 'i' and
- 'I' (yes, they are different letters) and OpenSSH isn't remotely
- prepared to deal with that. For now, the best we can do is to force
- OpenSSH to use the C/POSIX locale and try to preserve the UTF-8
- encoding if possible.
+ pointed out by sobrado@
- ok dtucker@
-
-commit c35995048f41239fc8895aadc3374c5f75180554
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Dec 9 12:52:02 2016 +1100
-
- exit is in stdlib.h not unistd.h (that's _exit).
-
-commit d399a8b914aace62418c0cfa20341aa37a192f98
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Dec 9 12:33:25 2016 +1100
-
- Include <unistd.h> for exit in utf8 locale test.
+ Upstream-ID: a6c44a0c2885330d322ee01fcfd7f6f209b1e15d
-commit 47b8c99ab3221188ad3926108dd9d36da3b528ec
+commit d29ba6f45086703fdcb894532848ada3427dfde6
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Dec 8 15:48:34 2016 +1100
+Date: Mon May 1 13:53:07 2017 +1000
- Check for utf8 local support before testing it.
-
- Check for utf8 local support and if not found, do not attempt to run the
- utf8 tests. Suggested by djm@
+ Define INT32_MAX and INT64_MAX if needed.
-commit 4089fc1885b3a2822204effbb02b74e3da58240d
+commit 329037e389f02ec95c8e16bf93ffede94d3d44ce
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Dec 8 12:57:24 2016 +1100
+Date: Mon May 1 13:19:41 2017 +1000
- Use AC_PATH_TOOL for krb5-config.
-
- This will use the host-prefixed version when cross compiling; patch from
- david.michael at coreos.com.
+ Wrap stdint.h in HAVE_STDINT_H
-commit b4867e0712c89b93be905220c82f0a15e6865d1e
+commit f382362e8dfb6b277f16779ab1936399d7f2af78
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Dec 6 07:48:01 2016 +0000
+Date: Mon May 1 02:27:11 2017 +0000
upstream commit
- make IdentityFile successfully load and use certificates that
- have no corresponding bare public key. E.g. just a private id_rsa and
- certificate id_rsa-cert.pub (and no id_rsa.pub).
-
- bz#2617 ok dtucker@
-
- Upstream-ID: c1e9699b8c0e3b63cc4189e6972e3522b6292604
-
-commit c9792783a98881eb7ed295680013ca97a958f8ac
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 25 14:04:21 2016 +1100
-
- Add a gnome-ssh-askpass3 target for GTK+3 version
+ remove unused variable
- Based on patch from Colin Watson via bz#2640
+ Upstream-ID: 66011f00819d0e71b14700449a98414033284516
-commit 7be85ae02b9de0993ce0a1d1e978e11329f6e763
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Nov 25 14:03:53 2016 +1100
+commit dd369320d2435b630a5974ab270d686dcd92d024
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:34:55 2017 +0000
- Make gnome-ssh-askpass2.c GTK+3-friendly
+ upstream commit
+
+ eliminate explicit specification of protocol in tests and
+ loops over protocol. We only support SSHv2 now.
- Patch from Colin Watson via bz#2640
+ Upstream-Regress-ID: 0082838a9b8a382b7ee9cbf0c1b9db727784fadd
-commit b9844a45c7f0162fd1b5465683879793d4cc4aaa
+commit 557f921aad004be15805e09fd9572969eb3d9321
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Dec 4 23:54:02 2016 +0000
+Date: Sun Apr 30 23:33:48 2017 +0000
upstream commit
- Fix public key authentication when multiple
- authentication is in use. Instead of deleting and re-preparing the entire
- keys list, just reset the 'used' flags; the keys list is already in a good
- order (with already- tried keys at the back)
-
- Analysis and patch from Vincent Brillault on bz#2642; ok dtucker@
+ remove SSHv1 support from unit tests
- Upstream-ID: 7123f12dc2f3bcaae715853035a97923d7300176
+ Upstream-Regress-ID: 395ca2aa48f1f7d23eefff6cb849ea733ca8bbfe
-commit f2398eb774075c687b13af5bc22009eb08889abe
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Dec 4 22:27:25 2016 +0000
+commit e77e1562716fb3da413e4c2397811017b762f5e3
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Mon May 1 00:03:18 2017 +0000
upstream commit
- Unlink PidFile on SIGHUP and always recreate it when the
- new sshd starts. Regression tests (and possibly other things) depend on the
- pidfile being recreated after SIGHUP, and unlinking it means it won't contain
- a stale pid if sshd fails to restart. ok djm@ markus@
+ fixup setting ciphercontext->plaintext (lost in SSHv1 purge),
+ though it isn't really used for much anymore.
- Upstream-ID: 132dd6dda0c77dd49d2f15b2573b5794f6160870
+ Upstream-ID: 859b8bce84ff4865b32097db5430349d04b9b747
+
+commit f7849e6c83a4e0f602dea6c834a24091c622d68e
+Author: Damien Miller <djm@mindrot.org>
+Date: Mon May 1 09:55:56 2017 +1000
+
+ remove configure --with-ssh1
-commit 85aa2efeba51a96bf6834f9accf2935d96150296
+commit f4a6a88ddb6dba6d2f7bfb9e2c9879fcc9633043
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Nov 30 03:01:33 2016 +0000
+Date: Sun Apr 30 23:29:10 2017 +0000
upstream commit
- test new behaviour of cert force-command restriction vs.
- authorized_key/ principals
+ flense SSHv1 support from ssh-agent, considerably
+ simplifying it
+
+ ok markus
- Upstream-Regress-ID: 399efa7469d40c404c0b0a295064ce75d495387c
+ Upstream-ID: 71d772cdcefcb29f76e01252e8361e6fc2dfc365
-commit 5d333131cd8519d022389cfd3236280818dae1bc
-Author: jmc@openbsd.org <jmc@openbsd.org>
-Date: Wed Nov 30 06:54:26 2016 +0000
+commit 930e8d2827853bc2e196c20c3e000263cc87fb75
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:28:41 2017 +0000
upstream commit
- tweak previous; while here fix up FILES and AUTHORS;
+ obliterate ssh1.h and some dead code that used it
+
+ ok markus@
- Upstream-ID: 93f6e54086145a75df8d8ec7d8689bdadbbac8fa
+ Upstream-ID: 1ca9159a9fb95618f9d51e069ac8e1131a087343
-commit 786d5994da79151180cb14a6cf157ebbba61c0cc
+commit a3710d5d529a34b8f56aa62db798c70e85d576a0
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Nov 30 03:07:37 2016 +0000
+Date: Sun Apr 30 23:28:12 2017 +0000
upstream commit
- add a whitelist of paths from which ssh-agent will load
- (via ssh-pkcs11-helper) a PKCS#11 module; ok markus@
+ exterminate the -1 flag from scp
+
+ ok markus@
- Upstream-ID: fe79769469d9cd6d26fe0dc15751b83ef2a06e8f
+ Upstream-ID: 26d247f7065da15056b209cef5f594ff591b89db
-commit 7844f357cdd90530eec81340847783f1f1da010b
+commit aebd0abfaa8a41e75d50f9f7934267b0a2d9acb4
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Nov 30 03:00:05 2016 +0000
+Date: Sun Apr 30 23:26:54 2017 +0000
upstream commit
- Add a sshd_config DisableForwaring option that disables
- X11, agent, TCP, tunnel and Unix domain socket forwarding, as well as
- anything else we might implement in the future.
+ purge the last traces of SSHv1 from the TTY modes
+ handling code
- This, like the 'restrict' authorized_keys flag, is intended to be a
- simple and future-proof way of restricting an account. Suggested as
- a complement to 'restrict' by Jann Horn; ok markus@
+ ok markus
- Upstream-ID: 203803f66e533a474086b38a59ceb4cf2410fcf7
+ Upstream-ID: 963a19f1e06577377c38a3b7ce468f121b966195
-commit fd6dcef2030d23c43f986d26979f84619c10589d
+commit dfa641f758d4b8b2608ab1b00abaf88df0a8e36a
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Wed Nov 30 02:57:40 2016 +0000
+Date: Sun Apr 30 23:26:16 2017 +0000
upstream commit
- When a forced-command appears in both a certificate and
- an authorized keys/principals command= restriction, refuse to accept the
- certificate unless they are identical.
+ remove the (in)famous SSHv1 CRC compensation attack
+ detector.
- The previous (documented) behaviour of having the certificate forced-
- command override the other could be a bit confused and more error-prone.
+ Despite your cameo in The Matrix movies, you will not be missed.
- Pointed out by Jann Horn of Project Zero; ok dtucker@
+ ok markus
- Upstream-ID: 79d811b6eb6bbe1221bf146dde6928f92d2cd05f
+ Upstream-ID: 44261fce51a56d93cdb2af7b6e184be629f667e0
-commit 7fc4766ac78abae81ee75b22b7550720bfa28a33
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Nov 30 00:28:31 2016 +0000
+commit e5d3bd36ef67d82092861f39b5bf422cb12b31a6
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:25:03 2017 +0000
upstream commit
- On startup, check to see if sshd is already daemonized
- and if so, skip the call to daemon() and do not rewrite the PidFile. This
- means that when sshd re-execs itself on SIGHUP the process ID will no longer
- change. Should address bz#2641. ok djm@ markus@.
-
- Upstream-ID: 5ea0355580056fb3b25c1fd6364307d9638a37b9
-
-commit c9f880c195c65f1dddcbc4ce9d6bfea7747debcc
-Author: Damien Miller <djm@mindrot.org>
-Date: Wed Nov 30 13:51:49 2016 +1100
-
- factor out common PRNG reseed before privdrop
+ undo some local debugging stuff that I committed by
+ accident
- Add a call to RAND_poll() to ensure than more than pid+time gets
- stirred into child processes states. Prompted by analysis from Jann
- Horn at Project Zero. ok dtucker@
+ Upstream-ID: fe5b31f69a60d47171836911f144acff77810217
-commit 79e4829ec81dead1b30999e1626eca589319a47f
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Nov 25 03:02:01 2016 +0000
+commit 3d6d09f2e90f4ad650ebda6520bf2da446f37f14
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:23:54 2017 +0000
upstream commit
- Allow PuTTY interop tests to run unattended. bz#2639,
- patch from cjwatson at debian.org.
+ remove SSHv1 support from packet and buffer APIs
+
+ ok markus@
- Upstream-Regress-ID: 4345253558ac23b2082aebabccd48377433b6fe0
+ Upstream-ID: bfc290053d40b806ecac46317d300677d80e1dc9
-commit 504c3a9a1bf090f6b27260fc3e8ea7d984d163dc
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Nov 25 02:56:49 2016 +0000
+commit 05164358577c82de18ed7373196bc7dbd8a3f79c
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:21:54 2017 +0000
upstream commit
- Reverse args to sshd-log-wrapper. Matches change in
- portable, where it allows sshd do be optionally run under Valgrind.
+ remove SSHv1-related buffers from client code
- Upstream-Regress-ID: b438d1c6726dc5caa2a45153e6103a0393faa906
+ Upstream-ID: dca5d01108f891861ceaf7ba1c0f2eb274e0c7dd
-commit bd13017736ec2f8f9ca498fe109fb0035f322733
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Fri Nov 25 02:49:18 2016 +0000
+commit 873d3e7d9a4707d0934fb4c4299354418f91b541
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:18:44 2017 +0000
upstream commit
- Fix typo in trace message; from portable.
+ remove KEY_RSA1
+
+ ok markus@
- Upstream-Regress-ID: 4c4a2ba0d37faf5fd230a91b4c7edb5699fbd73a
+ Upstream-ID: 7408517b077c892a86b581e19f82a163069bf133
-commit 7da751d8b007c7f3e814fd5737c2351440d78b4c
-Author: tb@openbsd.org <tb@openbsd.org>
-Date: Tue Nov 1 13:43:27 2016 +0000
+commit 788ac799a6efa40517f2ac0d895a610394298ffc
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:18:22 2017 +0000
upstream commit
- Clean up MALLOC_OPTIONS. For the unittests, move
- MALLOC_OPTIONS and TEST_ENV to unittets/Makefile.inc.
+ remove SSHv1 configuration options and man pages bits
- ok otto
+ ok markus@
- Upstream-Regress-ID: 890d497e0a38eeddfebb11cc429098d76cf29f12
+ Upstream-ID: 84638c23546c056727b7a7d653c72574e0f19424
-commit 36f58e68221bced35e06d1cca8d97c48807a8b71
-Author: tb@openbsd.org <tb@openbsd.org>
-Date: Mon Oct 31 23:45:08 2016 +0000
+commit e6882463a8ae0594aacb6d6575a6318a41973d84
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:17:37 2017 +0000
upstream commit
- Remove the obsolete A and P flags from MALLOC_OPTIONS.
-
- ok dtucker
+ remove SSH1 make flag and associated files ok markus@
- Upstream-Regress-ID: 6cc25024c8174a87e5734a0dc830194be216dd59
+ Upstream-ID: ba9feacc5787337c413db7cf26ea3d53f854cfef
-commit b0899ee26a6630883c0f2350098b6a35e647f512
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Tue Nov 29 03:54:50 2016 +0000
+commit cdccebdf85204bf7542b7fcc1aa2ea3f36661833
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:15:04 2017 +0000
upstream commit
- Factor out code to disconnect from controlling terminal
- into its own function. ok djm@
+ remove SSHv1 ciphers; ok markus@
- Upstream-ID: 39fd9e8ebd7222615a837312face5cc7ae962885
+ Upstream-ID: e5ebc5e540d7f23a8c1266db1839794d4d177890
-commit 54d022026aae4f53fa74cc636e4a032d9689b64d
+commit 97f4d3083b036ce3e68d6346a6140a22123d5864
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Nov 25 23:24:45 2016 +0000
+Date: Sun Apr 30 23:13:25 2017 +0000
upstream commit
- use sshbuf_allocate() to pre-allocate the buffer used for
- loading keys. This avoids implicit realloc inside the buffer code, which
- might theoretically leave fragments of the key on the heap. This doesn't
- appear to happen in practice for normal sized keys, but was observed for
- novelty oversize ones.
+ remove compat20/compat13/compat15 variables
- Pointed out by Jann Horn of Project Zero; ok markus@
+ ok markus@
- Upstream-ID: d620e1d46a29fdea56aeadeda120879eddc60ab1
+ Upstream-ID: 43802c035ceb3fef6c50c400e4ecabf12354691c
-commit a9c746088787549bb5b1ae3add7d06a1b6d93d5e
+commit 99f95ba82673d33215dce17bfa1512b57f54ec09
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Nov 25 23:22:04 2016 +0000
+Date: Sun Apr 30 23:11:45 2017 +0000
upstream commit
- split allocation out of sshbuf_reserve() into a separate
- sshbuf_allocate() function; ok markus@
+ remove options.protocol and client Protocol
+ configuration knob
+
+ ok markus@
- Upstream-ID: 11b8a2795afeeb1418d508a2c8095b3355577ec2
+ Upstream-ID: 5a967f5d06e2d004b0235457b6de3a9a314e9366
-commit f0ddedee460486fa0e32fefb2950548009e5026e
-Author: markus@openbsd.org <markus@openbsd.org>
-Date: Wed Nov 23 23:14:15 2016 +0000
+commit 56912dea6ef63dae4eb1194e5d88973a7c6c5740
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Sun Apr 30 23:10:43 2017 +0000
upstream commit
- allow ClientAlive{Interval,CountMax} in Match; ok dtucker,
- djm
+ unifdef WITH_SSH1 ok markus@
- Upstream-ID: 8beb4c1eadd588f1080b58932281983864979f55
+ Upstream-ID: 9716e62a883ef8826c57f4d33b4a81a9cc7755c7
-commit 1a6f9d2e2493d445cd9ee496e6e3c2a2f283f66a
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Tue Nov 8 22:04:34 2016 +0000
+commit d4084cd230f7319056559b00db8b99296dad49d5
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Sat Apr 29 06:06:01 2017 +0000
upstream commit
- unbreak DenyUsers; reported by henning@
+ tweak previous;
- Upstream-ID: 1c67d4148f5e953c35acdb62e7c08ae8e33f7cb2
+ Upstream-ID: a3abc6857455299aa42a046d232b7984568bceb9
-commit 010359b32659f455fddd2bd85fd7cc4d7a3b994a
+commit 249516e428e8461b46340a5df5d5ed1fbad2ccce
Author: djm@openbsd.org <djm@openbsd.org>
-Date: Sun Nov 6 05:46:37 2016 +0000
+Date: Sat Apr 29 04:12:25 2017 +0000
upstream commit
- Validate address ranges for AllowUser/DenyUsers at
- configuration load time and refuse to accept bad ones. It was previously
- possible to specify invalid CIDR address ranges (e.g. djm@127.1.2.3/55) and
- these would always match.
-
- Thanks to Laurence Parry for a detailed bug report. ok markus (for
- a previous diff version)
+ allow ssh-keygen to include arbitrary string or flag
+ certificate extensions and critical options. ok markus@ dtucker@
- Upstream-ID: 9dfcdd9672b06e65233ea4434c38226680d40bfb
+ Upstream-ID: 2cf28dd6c5489eb9fc136e0b667ac3ea10241646
-commit efb494e81d1317209256b38b49f4280897c61e69
-Author: djm@openbsd.org <djm@openbsd.org>
-Date: Fri Oct 28 03:33:52 2016 +0000
+commit 47a287bb6ac936c26b4f3ae63279c02902ded3b9
+Author: jmc@openbsd.org <jmc@openbsd.org>
+Date: Fri Apr 28 06:15:03 2017 +0000
upstream commit
- Improve pkcs11_add_provider() logging: demote some
- excessively verbose error()s to debug()s, include PKCS#11 provider name and
- slot in log messages where possible. bz#2610, based on patch from Jakub Jelen
+ sort;
- Upstream-ID: 3223ef693cfcbff9079edfc7e89f55bf63e1973d
+ Upstream-ID: 7e6b56e52b039cf44d0418e9de9aca20a2d2d15a
-commit 5ee3fb5affd7646f141749483205ade5fc54adaf
+commit 36465a76a79ad5040800711b41cf5f32249d5120
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Tue Nov 1 08:12:33 2016 +1100
-
- Use ptrace(PT_DENY_ATTACH, ..) on OS X.
-
-commit 315d2a4e674d0b7115574645cb51f968420ebb34
-Author: Damien Miller <djm@mindrot.org>
-Date: Fri Oct 28 14:34:07 2016 +1100
+Date: Fri Apr 28 14:44:28 2017 +1000
- Unbreak AES-CTR ciphers on old (~0.9.8) OpenSSL
+ Typo.
- ok dtucker@
+ Upstream-Regress-ID: 1e6b51ddf767cbad0a4e63eb08026c127e654308
-commit a9ff3950b8e80ff971b4d44bbce96df27aed28af
+commit 9d18cb7bdeb00b20205fd13d412aae8c0e0457ed
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 28 14:26:58 2016 +1100
+Date: Fri Apr 28 14:41:17 2017 +1000
- Move OPENSSL_NO_RIPEMD160 to compat.
+ Add 2 regress commits I applied by hand.
- Move OPENSSL_NO_RIPEMD160 to compat and add ifdefs to mac.c around the
- ripemd160 MACs.
+ Upstream-Regress-ID: 30c20180c87cbc99fa1020489fe7fd8245b6420c
+ Upstream-Regress-ID: 1e6b51ddf767cbad0a4e63eb08026c127e654308
-commit bce58885160e5db2adda3054c3b81fe770f7285a
+commit 9504ea6b27f9f0ece64e88582ebb9235e664a100
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 28 13:52:31 2016 +1100
+Date: Fri Apr 28 14:33:43 2017 +1000
- Check if RIPEMD160 is disabled in OpenSSL.
+ Merge integrity.sh rev 1.22.
+
+ Merge missing bits from Colin Watson's patch in bz#2658 which make integrity
+ tests more robust against timeouts. ok djm@
-commit d924640d4c355d1b5eca1f4cc60146a9975dbbff
+commit 06ec837a34542627e2183a412d6a9d2236f22140
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 28 13:38:19 2016 +1100
+Date: Fri Apr 28 14:30:03 2017 +1000
- Skip ssh1 specfic ciphers.
-
- cipher-3des1.c and cipher-bf1.c are specific to sshv1 so don't even try
- to compile them when Protocol 1 is not enabled.
+ Id sync for integrity.sh rev 1.21 which pulls in some shell portability fixes
-commit 79d078e7a49caef746516d9710ec369ba45feab6
+commit e0194b471efe7d3daedc9cc66686cb1ab69d3be8
Author: jsg@openbsd.org <jsg@openbsd.org>
-Date: Tue Oct 25 04:08:13 2016 +0000
+Date: Mon Apr 17 11:02:31 2017 +0000
upstream commit
- Fix logic in add_local_forward() that inverted a test
- when code was refactored out into bind_permitted(). This broke ssh port
- forwarding for non-priv ports as a non root user.
-
- ok dtucker@ 'looks good' deraadt@
+ Change COMPILER_VERSION tests which limited additional
+ warnings to gcc4 to instead skip them on gcc3 as clang can handle
+ -Wpointer-sign and -Wold-style-definition.
- Upstream-ID: ddb8156ca03cc99997de284ce7777536ff9570c9
+ Upstream-Regress-ID: e48d7dc13e48d9334b8195ef884dfbc51316012f
-commit a903e315dee483e555c8a3a02c2946937f9b4e5d
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Mon Oct 24 01:09:17 2016 +0000
+commit 6830be90e71f46bcd182a9202b151eaf2b299434
+Author: djm@openbsd.org <djm@openbsd.org>
+Date: Fri Apr 28 03:24:53 2017 +0000
upstream commit
- Remove dead breaks, found via opencoverage.net. ok
- deraadt@
+ include key fingerprint in "Offering public key" debug
+ message
- Upstream-ID: ad9cc655829d67fad219762810770787ba913069
+ Upstream-ID: 964749f820c2ed4cf6a866268b1a05e907315c52
-commit b4e96b4c9bea4182846e4942ba2048e6d708ee54
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Wed Oct 26 08:43:25 2016 +1100
+commit 066437187e16dcafcbc19f9402ef0e6575899b1d
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Fri Apr 28 03:21:12 2017 +0000
- Use !=NULL instead of >0 for getdefaultproj.
+ upstream commit
+
+ Avoid relying on implementation-specific behavior when
+ detecting whether the timestamp or file size overflowed. If time_t and off_t
+ are not either 32-bit or 64-bit scp will exit with an error. OK djm@
- getdefaultproj() returns a pointer so test it for NULL inequality
- instead of >0. Fixes compiler warning and is more correct. Patch from
- David Binderman.
+ Upstream-ID: f31caae73ddab6df496b7bbbf7da431e267ad135
-commit 1c4ef0b808d3d38232aeeb1cebb7e9a43def42c5
+commit 68d3a2a059183ebd83b15e54984ffaced04d2742
Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Sun Oct 23 22:04:05 2016 +0000
+Date: Fri Apr 28 03:20:27 2017 +0000
upstream commit
- Factor out "can bind to low ports" check into its own function. This will
- make it easier for Portable to support platforms with permissions models
- other than uid==0 (eg bz#2625). ok djm@, "doesn't offend me too much"
- deraadt@.
+ Add SyslogFacility option to ssh(1) matching the
+ equivalent option in sshd(8). bz#2705, patch from erahn at arista.com, ok
+ djm@
- Upstream-ID: 86213df4183e92b8f189a6d2dac858c994bfface
+ Upstream-ID: d5115c2c0193ceb056ed857813b2a7222abda9ed
-commit 0b9ee623d57e5de7e83e66fd61a7ba9a5be98894
-Author: dtucker@openbsd.org <dtucker@openbsd.org>
-Date: Wed Oct 19 23:21:56 2016 +0000
+commit e13aad66e73a14b062d13aee4e98f1e21a3f6a14
+Author: jsg@openbsd.org <jsg@openbsd.org>
+Date: Thu Apr 27 13:40:05 2017 +0000
upstream commit
- When tearing down ControlMaster connecctions, don't
- pollute stderr when LogLevel=quiet. Patch from Tim Kuijsten via tech@.
+ remove a static array unused since rev 1.306 spotted by
+ clang ok djm@
- Upstream-ID: d9b3a68b2a7c2f2fc7f74678e29a4618d55ceced
-
-commit 09e6a7d8354224933febc08ddcbc2010f542284e
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Mon Oct 24 09:06:18 2016 +1100
-
- Wrap stdint.h include in ifdef.
+ Upstream-ID: 249b3eed2446f6074ba2219ccc46919dd235a7b8
-commit 08d9e9516e587b25127545c029e5464b2e7f2919
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 21 09:46:46 2016 +1100
+commit 91bd2181866659f00714903e78e1c3edd4c45f3d
+Author: millert@openbsd.org <millert@openbsd.org>
+Date: Thu Apr 27 11:53:12 2017 +0000
- Fix formatting.
+ upstream commit
+
+ Avoid potential signed int overflow when parsing the file
+ size. Use strtoul() instead of parsing manually. OK djm@
+
+ Upstream-ID: 1f82640861c7d905bbb05e7d935d46b0419ced02
-commit 461f50e7ab8751d3a55e9158c44c13031db7ba1d
+commit 17a54a03f5a1d35e33cc24e22cd7a9d0f6865dc4
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 21 06:55:58 2016 +1100
+Date: Tue Apr 25 08:32:27 2017 +1000
- Update links to https.
+ Fix typo in "socketcall".
- www.openssh.com now supports https and ftp.openbsd.org no longer
- supports ftp. Make all links to these https.
+ Pointed out by jjelen at redhat.com.
-commit dd4e7212a6141f37742de97795e79db51e4427ad
+commit 8b0eee148f7cf8b248c30d1bae57300f2cc5aafd
Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 21 06:48:46 2016 +1100
+Date: Mon Apr 24 19:40:31 2017 +1000
- Update host key generation examples.
+ Deny socketcall in seccomp filter on ppc64le.
+
+ OpenSSL is using socket() calls (in FIPS mode) when handling ECDSA keys
+ in privsep child. The socket() syscall is already denied in the seccomp
+ filter, but in ppc64le kernel, it is implemented using socketcall()
+ syscall, which is not denied yet (only SYS_SHUTDOWN is allowed) and
+ therefore fails hard.
- Remove ssh1 host key generation, add ssh-keygen -A
+ Patch from jjelen at redhat.com.
-commit 6d49ae82634c67e9a4d4af882bee20b40bb8c639
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Fri Oct 21 05:22:55 2016 +1100
+commit f8500b2be599053daa05248a86a743232ec6a536
+Author: schwarze@openbsd.org <schwarze@openbsd.org>
+Date: Mon Apr 17 14:31:23 2017 +0000
- Update links.
+ upstream commit
- Make links to openssh.com HTTPS now that it's supported, point release
- notes link to the HTML release notes page, and update a couple of other
- links and bits of text.
+ Recognize nl_langinfo(CODESET) return values "646" and ""
+ as aliases for "US-ASCII", useful for different versions of NetBSD and
+ Solaris. Found by dtucker@ and by Tom G. Christensen <tgc at jupiterrise dot
+ com>. OK dtucker@ deraadt@
+
+ Upstream-ID: 38c2133817cbcae75c88c63599ac54228f0fa384
-commit fe0d1ca6ace06376625084b004ee533f2c2ea9d6
-Author: Darren Tucker <dtucker@zip.com.au>
-Date: Thu Oct 20 03:42:09 2016 +1100
+commit 7480dfedf8c5c93baaabef444b3def9331e86ad5
+Author: jsg@openbsd.org <jsg@openbsd.org>
+Date: Mon Apr 17 11:02:31 2017 +0000
- Remote channels .orig and .rej files.
+ upstream commit
+
+ Change COMPILER_VERSION tests which limited additional
+ warnings to gcc4 to instead skip them on gcc3 as clang can handle
+ -Wpointer-sign and -Wold-style-definition.
- These files were incorrectly added during an OpenBSD sync.
+ Upstream-ID: 5cbe348aa76dc1adf55be6c0e388fafaa945439a
diff --git a/INSTALL b/INSTALL
index 3fd265dbfaea..f1f8f00f3390 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,264 +1,264 @@
1. Prerequisites
----------------
A C compiler. Any C89 or better compiler should work. Where supported,
configure will attempt to enable the compiler's run-time integrity checking
options. Some notes about specific compilers:
- clang: -ftrapv and -sanitize=integer require the compiler-rt runtime
(CC=clang LDFLAGS=--rtlib=compiler-rt ./configure)
You will need working installations of Zlib and libcrypto (LibreSSL /
OpenSSL)
Zlib 1.1.4 or 1.2.1.2 or greater (earlier 1.2.x versions have problems):
http://www.gzip.org/zlib/
-libcrypto (LibreSSL or OpenSSL >= 1.0.1 < 1.1.0)
-LibreSSL http://www.libressl.org/ ; or
-OpenSSL http://www.openssl.org/
+libcrypto from either of:
+ - LibreSSL (http://www.libressl.org/)
+ - OpenSSL 1.0.x >= 1.0.1 or 1.1.0 >= 1.1.0g (http://www.openssl.org/)
LibreSSL/OpenSSL should be compiled as a position-independent library
(i.e. with -fPIC) otherwise OpenSSH will not be able to link with it.
If you must use a non-position-independent libcrypto, then you may need
-to configure OpenSSH --without-pie. Note that because of API changes,
-OpenSSL 1.1.x is not currently supported.
+to configure OpenSSH --without-pie. Note that due to a bug in EVP_CipherInit
+OpenSSL 1.1 versions prior to 1.1.0g can't be used.
The remaining items are optional.
NB. If you operating system supports /dev/random, you should configure
libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's
direct support of /dev/random, or failing that, either prngd or egd
PRNGD:
If your system lacks kernel-based random collection, the use of Lutz
Jaenicke's PRNGd is recommended.
http://prngd.sourceforge.net/
EGD:
If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is
supported only if libcrypto supports it.
http://egd.sourceforge.net/
PAM:
OpenSSH can utilise Pluggable Authentication Modules (PAM) if your
system supports it. PAM is standard most Linux distributions, Solaris,
HP-UX 11, AIX >= 5.2, FreeBSD and NetBSD.
Information about the various PAM implementations are available:
Solaris PAM: http://www.sun.com/software/solaris/pam/
Linux PAM: http://www.kernel.org/pub/linux/libs/pam/
OpenPAM: http://www.openpam.org/
If you wish to build the GNOME passphrase requester, you will need the GNOME
libraries and headers.
GNOME:
http://www.gnome.org/
Alternatively, Jim Knoble <jmknoble@pobox.com> has written an excellent X11
passphrase requester. This is maintained separately at:
http://www.jmknoble.net/software/x11-ssh-askpass/
LibEdit:
sftp supports command-line editing via NetBSD's libedit. If your platform
has it available natively you can use that, alternatively you might try
these multi-platform ports:
http://www.thrysoee.dk/editline/
http://sourceforge.net/projects/libedit/
LDNS:
LDNS is a DNS BSD-licensed resolver library which supports DNSSEC.
http://nlnetlabs.nl/projects/ldns/
Autoconf:
If you modify configure.ac or configure doesn't exist (eg if you checked
the code out of git yourself) then you will need autoconf-2.69 to rebuild
the automatically generated files by running "autoreconf". Earlier
versions may also work but this is not guaranteed.
http://www.gnu.org/software/autoconf/
Basic Security Module (BSM):
Native BSM support is known to exist in Solaris from at least 2.5.1,
FreeBSD 6.1 and OS X. Alternatively, you may use the OpenBSM
implementation (http://www.openbsm.org).
makedepend:
https://www.x.org/archive/individual/util/
If you are making significant changes to the code you may need to rebuild
the dependency (.depend) file using "make depend", which requires the
"makedepend" tool from the X11 distribution.
2. Building / Installation
--------------------------
To install OpenSSH with default options:
./configure
make
make install
This will install the OpenSSH binaries in /usr/local/bin, configuration files
in /usr/local/etc, the server in /usr/local/sbin, etc. To specify a different
installation prefix, use the --prefix option to configure:
./configure --prefix=/opt
make
make install
Will install OpenSSH in /opt/{bin,etc,lib,sbin}. You can also override
specific paths, for example:
./configure --prefix=/opt --sysconfdir=/etc/ssh
make
make install
This will install the binaries in /opt/{bin,lib,sbin}, but will place the
configuration files in /etc/ssh.
If you are using Privilege Separation (which is enabled by default)
then you will also need to create the user, group and directory used by
sshd for privilege separation. See README.privsep for details.
If you are using PAM, you may need to manually install a PAM control
file as "/etc/pam.d/sshd" (or wherever your system prefers to keep
them). Note that the service name used to start PAM is __progname,
which is the basename of the path of your sshd (e.g., the service name
for /usr/sbin/osshd will be osshd). If you have renamed your sshd
executable, your PAM configuration may need to be modified.
A generic PAM configuration is included as "contrib/sshd.pam.generic",
you may need to edit it before using it on your system. If you are
using a recent version of Red Hat Linux, the config file in
contrib/redhat/sshd.pam should be more useful. Failure to install a
valid PAM file may result in an inability to use password
authentication. On HP-UX 11 and Solaris, the standard /etc/pam.conf
configuration will work with sshd (sshd will match the other service
name).
There are a few other options to the configure script:
--with-audit=[module] enable additional auditing via the specified module.
Currently, drivers for "debug" (additional info via syslog) and "bsm"
(Sun's Basic Security Module) are supported.
--with-pam enables PAM support. If PAM support is compiled in, it must
also be enabled in sshd_config (refer to the UsePAM directive).
--with-prngd-socket=/some/file allows you to enable EGD or PRNGD
support and to specify a PRNGd socket. Use this if your Unix lacks
/dev/random.
--with-prngd-port=portnum allows you to enable EGD or PRNGD support
and to specify a EGD localhost TCP port. Use this if your Unix lacks
/dev/random.
--with-lastlog=FILE will specify the location of the lastlog file.
./configure searches a few locations for lastlog, but may not find
it if lastlog is installed in a different place.
--without-lastlog will disable lastlog support entirely.
--with-osfsia, --without-osfsia will enable or disable OSF1's Security
Integration Architecture. The default for OSF1 machines is enable.
--with-md5-passwords will enable the use of MD5 passwords. Enable this
if your operating system uses MD5 passwords and the system crypt() does
not support them directly (see the crypt(3/3c) man page). If enabled, the
resulting binary will support both MD5 and traditional crypt passwords.
--with-utmpx enables utmpx support. utmpx support is automatic for
some platforms.
--without-shadow disables shadow password support.
--with-ipaddr-display forces the use of a numeric IP address in the
$DISPLAY environment variable. Some broken systems need this.
--with-default-path=PATH allows you to specify a default $PATH for sessions
started by sshd. This replaces the standard path entirely.
--with-pid-dir=PATH specifies the directory in which the sshd.pid file is
created.
--with-xauth=PATH specifies the location of the xauth binary
--with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL
libraries are installed.
--with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
If you need to pass special options to the compiler or linker, you
can specify these as environment variables before running ./configure.
For example:
CC="/usr/foo/cc" CFLAGS="-O" LDFLAGS="-s" LIBS="-lrubbish" ./configure
3. Configuration
----------------
The runtime configuration files are installed by in ${prefix}/etc or
whatever you specified as your --sysconfdir (/usr/local/etc by default).
The default configuration should be instantly usable, though you should
review it to ensure that it matches your security requirements.
To generate a host key, run "make host-key". Alternately you can do so
manually using the following commands:
ssh-keygen -t [type] -f /etc/ssh/ssh_host_key -N ""
for each of the types you wish to generate (rsa, dsa or ecdsa) or
ssh-keygen -A
to generate keys for all supported types.
Replacing /etc/ssh with the correct path to the configuration directory.
(${prefix}/etc or whatever you specified with --sysconfdir during
configuration)
If you have configured OpenSSH with EGD support, ensure that EGD is
running and has collected some Entropy.
For more information on configuration, please refer to the manual pages
for sshd, ssh and ssh-agent.
4. (Optional) Send survey
-------------------------
$ make survey
[check the contents of the file "survey" to ensure there's no information
that you consider sensitive]
$ make send-survey
This will send configuration information for the currently configured
host to a survey address. This will help determine which configurations
are actually in use, and what valid combinations of configure options
exist. The raw data is available only to the OpenSSH developers, however
summary data may be published.
5. Problems?
------------
If you experience problems compiling, installing or running OpenSSH.
Please refer to the "reporting bugs" section of the webpage at
https://www.openssh.com/
diff --git a/Makefile.in b/Makefile.in
index 126b2c742bd3..6f001bb360df 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,658 +1,660 @@
# uncomment if you run a non bourne compatible shell. Ie. csh
#SHELL = @SH@
AUTORECONF=autoreconf
prefix=@prefix@
exec_prefix=@exec_prefix@
bindir=@bindir@
sbindir=@sbindir@
libexecdir=@libexecdir@
datadir=@datadir@
datarootdir=@datarootdir@
mandir=@mandir@
mansubdir=@mansubdir@
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
DESTDIR=
VPATH=@srcdir@
SSH_PROGRAM=@bindir@/ssh
ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
STRIP_OPT=@STRIP_OPT@
TEST_SHELL=@TEST_SHELL@
PATHS= -DSSHDIR=\"$(sysconfdir)\" \
-D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
-D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \
-D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \
-D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \
-D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
-D_PATH_SSH_PIDDIR=\"$(piddir)\" \
-D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\"
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
LIBS=@LIBS@
K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
SSHLIBS=@SSHLIBS@
SSHDLIBS=@SSHDLIBS@
LIBEDIT=@LIBEDIT@
AR=@AR@
AWK=@AWK@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
SED=@SED@
ENT=@ENT@
XAUTH_PATH=@XAUTH_PATH@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
MKDIR_P=@MKDIR_P@
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
XMSS_OBJS=\
ssh-xmss.o \
sshkey-xmss.o \
xmss_commons.o \
xmss_fast.o \
xmss_hash.o \
xmss_hash_address.o \
xmss_wots.o
LIBOPENSSH_OBJS=\
ssh_api.o \
ssherr.o \
sshbuf.o \
sshkey.o \
sshbuf-getput-basic.o \
sshbuf-misc.o \
sshbuf-getput-crypto.o \
krl.o \
bitmap.o \
${XMSS_OBJS}
LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
authfd.o authfile.o \
canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \
cipher-ctr.o cleanup.o \
compat.o crc32.o fatal.o hostfile.o \
- log.o match.o moduli.o nchan.o packet.o opacket.o \
+ log.o match.o moduli.o nchan.o packet.o \
readpass.o ttymodes.o xmalloc.o addrmatch.o \
atomicio.o dispatch.o mac.o uuencode.o misc.o utf8.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
ssh-pkcs11.o smult_curve25519_ref.o \
poly1305.o chacha.o cipher-chachapoly.o \
ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \
sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
- kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \
- kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \
+ kexgexc.o kexgexs.o \
+ sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \
platform-pledge.o platform-tracing.o platform-misc.o
+
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
sshconnect.o sshconnect2.o mux.o
SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
audit.o audit-bsm.o audit-linux.o platform.o \
sshpty.o sshlogin.o servconf.o serverloop.o \
auth.o auth2.o auth-options.o session.o \
auth2-chall.o groupaccess.o \
auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor.o monitor_wrap.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
sftp-server.o sftp-common.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
sandbox-solaris.o uidswap.o
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
MANTYPE = @MANTYPE@
CONFIGFILES=sshd_config.out ssh_config.out moduli.out
CONFIGFILES_IN=sshd_config ssh_config moduli
PATHSUBS = \
-e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
-e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
-e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
-e 's|/usr/libexec|$(libexecdir)|g' \
-e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \
-e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \
-e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \
-e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \
-e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \
-e 's|/etc/ssh/ssh_host_ed25519_key|$(sysconfdir)/ssh_host_ed25519_key|g' \
-e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \
-e 's|/etc/moduli|$(sysconfdir)/moduli|g' \
-e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \
-e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \
-e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \
-e 's|/var/empty|$(PRIVSEP_PATH)|g' \
-e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g'
FIXPATHSCMD = $(SED) $(PATHSUBS)
FIXALGORITHMSCMD= $(SHELL) $(srcdir)/fixalgorithms $(SED) \
@UNSUPPORTED_ALGORITHMS@
all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
$(LIBSSH_OBJS): Makefile.in config.h
$(SSHOBJS): Makefile.in config.h
$(SSHDOBJS): Makefile.in config.h
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
$(LIBCOMPAT): always
(cd openbsd-compat && $(MAKE))
always:
libssh.a: $(LIBSSH_OBJS)
$(AR) rv $@ $(LIBSSH_OBJS)
$(RANLIB) $@
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
$(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o
$(LD) -o $@ scp.o progressmeter.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o
$(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
$(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
$(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)
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
$(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o
$(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
$(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
# test driver for the loginrec code - not built by default
logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
$(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
$(MANPAGES): $(MANPAGES_IN)
if test "$(MANTYPE)" = "cat"; then \
manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \
else \
manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \
fi; \
if test "$(MANTYPE)" = "man"; then \
$(FIXPATHSCMD) $${manpage} | $(FIXALGORITHMSCMD) | \
$(AWK) -f $(srcdir)/mdoc2man.awk > $@; \
else \
$(FIXPATHSCMD) $${manpage} | $(FIXALGORITHMSCMD) > $@; \
fi
$(CONFIGFILES): $(CONFIGFILES_IN)
conffile=`echo $@ | sed 's/.out$$//'`; \
$(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
moduli:
echo
clean: regressclean
rm -f *.o *.a $(TARGETS) logintest config.cache config.log
rm -f *.out core survey
rm -f regress/check-perm$(EXEEXT)
rm -f regress/mkdtemp$(EXEEXT)
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
rm -f regress/unittests/sshbuf/*.o
rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT)
rm -f regress/unittests/sshkey/*.o
rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT)
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT)
rm -f regress/unittests/conversion/*.o
rm -f regress/unittests/conversion/test_conversion$(EXEEXT)
rm -f regress/unittests/hostkeys/*.o
rm -f regress/unittests/hostkeys/test_hostkeys$(EXEEXT)
rm -f regress/unittests/kex/*.o
rm -f regress/unittests/kex/test_kex$(EXEEXT)
rm -f regress/unittests/match/*.o
rm -f regress/unittests/match/test_match$(EXEEXT)
rm -f regress/unittests/utf8/*.o
rm -f regress/unittests/utf8/test_utf8$(EXEEXT)
rm -f regress/misc/kexfuzz/*.o
rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
(cd openbsd-compat && $(MAKE) clean)
distclean: regressclean
rm -f *.o *.a $(TARGETS) logintest config.cache config.log
rm -f *.out core opensshd.init openssh.xml
rm -f Makefile buildpkg.sh config.h config.status
rm -f survey.sh openbsd-compat/regress/Makefile *~
rm -rf autom4te.cache
rm -f regress/check-perm
rm -f regress/mkdtemp
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
rm -f regress/unittests/sshbuf/*.o
rm -f regress/unittests/sshbuf/test_sshbuf
rm -f regress/unittests/sshkey/*.o
rm -f regress/unittests/sshkey/test_sshkey
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap
rm -f regress/unittests/conversion/*.o
rm -f regress/unittests/conversion/test_conversion
rm -f regress/unittests/hostkeys/*.o
rm -f regress/unittests/hostkeys/test_hostkeys
rm -f regress/unittests/kex/*.o
rm -f regress/unittests/kex/test_kex
rm -f regress/unittests/match/*.o
rm -f regress/unittests/match/test_match
rm -f regress/unittests/utf8/*.o
rm -f regress/unittests/utf8/test_utf8
rm -f regress/misc/kexfuzz/*.o
rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
(cd openbsd-compat && $(MAKE) distclean)
if test -d pkg ; then \
rm -fr pkg ; \
fi
veryclean: distclean
rm -f configure config.h.in *.0
cleandir: veryclean
mrproper: veryclean
realclean: veryclean
catman-do:
@for f in $(MANPAGES_IN) ; do \
base=`echo $$f | sed 's/\..*$$//'` ; \
echo "$$f -> $$base.0" ; \
$(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \
>$$base.0 ; \
done
depend: depend-rebuild
rm -f .depend.bak
depend-rebuild:
rm -f config.h
touch config.h
makedepend -w1000 -Y. -f .depend *.c 2>/dev/null
rm -f config.h
depend-check: depend-rebuild
cmp .depend .depend.bak || (echo .depend stale && exit 1)
distprep: catman-do depend-check
$(AUTORECONF)
-rm -rf autom4te.cache .depend.bak
install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
check-config:
-$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
install-files:
$(MKDIR_P) $(DESTDIR)$(bindir)
$(MKDIR_P) $(DESTDIR)$(sbindir)
$(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)1
$(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)5
$(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)8
$(MKDIR_P) $(DESTDIR)$(libexecdir)
$(MKDIR_P) -m 0755 $(DESTDIR)$(PRIVSEP_PATH)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
$(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
$(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
$(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
$(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
$(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
$(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5
$(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
$(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
$(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
$(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
$(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
$(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
$(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
install-sysconf:
$(MKDIR_P) $(DESTDIR)$(sysconfdir)
@if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \
$(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
else \
echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \
fi
@if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \
$(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \
else \
echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \
fi
@if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \
if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \
echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \
else \
$(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \
fi ; \
else \
echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \
fi
host-key: ssh-keygen$(EXEEXT)
@if [ -z "$(DESTDIR)" ] ; then \
./ssh-keygen -A; \
fi
host-key-force: ssh-keygen$(EXEEXT) ssh$(EXEEXT)
./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
./ssh-keygen -t ed25519 -f $(DESTDIR)$(sysconfdir)/ssh_host_ed25519_key -N ""
if ./ssh -Q key | grep ecdsa >/dev/null ; then \
./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""; \
fi
uninstallall: uninstall
-rm -f $(DESTDIR)$(sysconfdir)/ssh_config
-rm -f $(DESTDIR)$(sysconfdir)/sshd_config
-rmdir $(DESTDIR)$(sysconfdir)
-rmdir $(DESTDIR)$(bindir)
-rmdir $(DESTDIR)$(sbindir)
-rmdir $(DESTDIR)$(mandir)/$(mansubdir)1
-rmdir $(DESTDIR)$(mandir)/$(mansubdir)8
-rmdir $(DESTDIR)$(mandir)
-rmdir $(DESTDIR)$(libexecdir)
uninstall:
-rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
-rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT)
-rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
-rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
-rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
-rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
-rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
regress-prep:
$(MKDIR_P) `pwd`/regress/unittests/test_helper
$(MKDIR_P) `pwd`/regress/unittests/sshbuf
$(MKDIR_P) `pwd`/regress/unittests/sshkey
$(MKDIR_P) `pwd`/regress/unittests/bitmap
$(MKDIR_P) `pwd`/regress/unittests/conversion
$(MKDIR_P) `pwd`/regress/unittests/hostkeys
$(MKDIR_P) `pwd`/regress/unittests/kex
$(MKDIR_P) `pwd`/regress/unittests/match
$(MKDIR_P) `pwd`/regress/unittests/utf8
$(MKDIR_P) `pwd`/regress/misc/kexfuzz
[ -f `pwd`/regress/Makefile ] || \
ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
REGRESSLIBS=libssh.a $(LIBCOMPAT)
regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/setuid-allowed.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress/mkdtemp$(EXEEXT): $(srcdir)/regress/mkdtemp.c $(REGRESSLIBS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/mkdtemp.c \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_HELPER_OBJS=\
regress/unittests/test_helper/test_helper.o \
regress/unittests/test_helper/fuzz.o
regress/unittests/test_helper/libtest_helper.a: ${UNITTESTS_TEST_HELPER_OBJS}
$(AR) rv $@ $(UNITTESTS_TEST_HELPER_OBJS)
$(RANLIB) $@
UNITTESTS_TEST_SSHBUF_OBJS=\
regress/unittests/sshbuf/tests.o \
regress/unittests/sshbuf/test_sshbuf.o \
regress/unittests/sshbuf/test_sshbuf_getput_basic.o \
regress/unittests/sshbuf/test_sshbuf_getput_crypto.o \
regress/unittests/sshbuf/test_sshbuf_misc.o \
regress/unittests/sshbuf/test_sshbuf_fuzz.o \
regress/unittests/sshbuf/test_sshbuf_getput_fuzz.o \
regress/unittests/sshbuf/test_sshbuf_fixed.o
regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHBUF_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_SSHKEY_OBJS=\
regress/unittests/sshkey/test_fuzz.o \
regress/unittests/sshkey/tests.o \
regress/unittests/sshkey/common.o \
regress/unittests/sshkey/test_file.o \
regress/unittests/sshkey/test_sshkey.o
regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHKEY_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_BITMAP_OBJS=\
regress/unittests/bitmap/tests.o
regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_BITMAP_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_CONVERSION_OBJS=\
regress/unittests/conversion/tests.o
regress/unittests/conversion/test_conversion$(EXEEXT): \
${UNITTESTS_TEST_CONVERSION_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_CONVERSION_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_KEX_OBJS=\
regress/unittests/kex/tests.o \
regress/unittests/kex/test_kex.o
regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_KEX_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_HOSTKEYS_OBJS=\
regress/unittests/hostkeys/tests.o \
regress/unittests/hostkeys/test_iterate.o
regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \
${UNITTESTS_TEST_HOSTKEYS_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_HOSTKEYS_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_MATCH_OBJS=\
regress/unittests/match/tests.o
regress/unittests/match/test_match$(EXEEXT): \
${UNITTESTS_TEST_MATCH_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MATCH_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
UNITTESTS_TEST_UTF8_OBJS=\
regress/unittests/utf8/tests.o
regress/unittests/utf8/test_utf8$(EXEEXT): \
${UNITTESTS_TEST_UTF8_OBJS} \
regress/unittests/test_helper/libtest_helper.a libssh.a
$(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_UTF8_OBJS) \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
MISC_KEX_FUZZ_OBJS=\
regress/misc/kexfuzz/kexfuzz.o
regress/misc/kexfuzz/kexfuzz$(EXEEXT): ${MISC_KEX_FUZZ_OBJS} libssh.a
$(LD) -o $@ $(LDFLAGS) $(MISC_KEX_FUZZ_OBJS) \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
regress-binaries: regress/modpipe$(EXEEXT) \
regress/setuid-allowed$(EXEEXT) \
regress/netcat$(EXEEXT) \
regress/check-perm$(EXEEXT) \
regress/mkdtemp$(EXEEXT) \
regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
regress/unittests/sshkey/test_sshkey$(EXEEXT) \
regress/unittests/bitmap/test_bitmap$(EXEEXT) \
regress/unittests/conversion/test_conversion$(EXEEXT) \
regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \
regress/unittests/kex/test_kex$(EXEEXT) \
regress/unittests/match/test_match$(EXEEXT) \
regress/unittests/utf8/test_utf8$(EXEEXT) \
regress/misc/kexfuzz/kexfuzz$(EXEEXT)
tests interop-tests t-exec unit: regress-prep regress-binaries $(TARGETS)
BUILDDIR=`pwd`; \
TEST_SSH_SCP="$${BUILDDIR}/scp"; \
TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
TEST_SSH_SSHAGENT="$${BUILDDIR}/ssh-agent"; \
TEST_SSH_SSHADD="$${BUILDDIR}/ssh-add"; \
TEST_SSH_SSHKEYGEN="$${BUILDDIR}/ssh-keygen"; \
TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
TEST_SSH_SSHKEYSCAN="$${BUILDDIR}/ssh-keyscan"; \
TEST_SSH_SFTP="$${BUILDDIR}/sftp"; \
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server"; \
+ TEST_SSH_SSHPKCS11HELPER="$${BUILDDIR}/ssh-pkcs11-helper"; \
TEST_SSH_PLINK="plink"; \
TEST_SSH_PUTTYGEN="puttygen"; \
TEST_SSH_CONCH="conch"; \
TEST_SSH_IPV6="@TEST_SSH_IPV6@" ; \
TEST_SSH_UTF8="@TEST_SSH_UTF8@" ; \
TEST_SSH_ECC="@TEST_SSH_ECC@" ; \
cd $(srcdir)/regress || exit $$?; \
$(MAKE) \
.OBJDIR="$${BUILDDIR}/regress" \
.CURDIR="`pwd`" \
BUILDDIR="$${BUILDDIR}" \
OBJ="$${BUILDDIR}/regress/" \
PATH="$${BUILDDIR}:$${PATH}" \
TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
TEST_MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
TEST_SSH_SCP="$${TEST_SSH_SCP}" \
TEST_SSH_SSH="$${TEST_SSH_SSH}" \
TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
TEST_SSH_SSHAGENT="$${TEST_SSH_SSHAGENT}" \
TEST_SSH_SSHADD="$${TEST_SSH_SSHADD}" \
TEST_SSH_SSHKEYGEN="$${TEST_SSH_SSHKEYGEN}" \
TEST_SSH_SSHPKCS11HELPER="$${TEST_SSH_SSHPKCS11HELPER}" \
TEST_SSH_SSHKEYSCAN="$${TEST_SSH_SSHKEYSCAN}" \
TEST_SSH_SFTP="$${TEST_SSH_SFTP}" \
TEST_SSH_SFTPSERVER="$${TEST_SSH_SFTPSERVER}" \
TEST_SSH_PLINK="$${TEST_SSH_PLINK}" \
TEST_SSH_PUTTYGEN="$${TEST_SSH_PUTTYGEN}" \
TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
TEST_SSH_UTF8="$${TEST_SSH_UTF8}" \
TEST_SSH_ECC="$${TEST_SSH_ECC}" \
TEST_SHELL="${TEST_SHELL}" \
EXEEXT="$(EXEEXT)" \
$@ && echo all tests passed
compat-tests: $(LIBCOMPAT)
(cd openbsd-compat/regress && $(MAKE))
regressclean:
if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \
(cd regress && $(MAKE) clean) \
fi
survey: survey.sh ssh
@$(SHELL) ./survey.sh > survey
@echo 'The survey results have been placed in the file "survey" in the'
@echo 'current directory. Please review the file then send with'
@echo '"make send-survey".'
send-survey: survey
mail portable-survey@mindrot.org <survey
package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
sh buildpkg.sh; \
fi
# @DEPEND@
diff --git a/OVERVIEW b/OVERVIEW
index 515567f45b0c..cec7cd75b51c 100644
--- a/OVERVIEW
+++ b/OVERVIEW
@@ -1,161 +1,162 @@
[Note: This file has not been updated for OpenSSH versions after
OpenSSH-1.2 and should be considered OBSOLETE. It has been left in
the distribution because some of its information may still be useful
to developers.]
This document is intended for those who wish to read the ssh source
code. This tries to give an overview of the structure of the code.
Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
Updated 17 Nov 1995.
Updated 19 Oct 1999 for OpenSSH-1.2
Updated 20 May 2001 note obsolete for > OpenSSH-1.2
The software consists of ssh (client), sshd (server), scp, sdist, and
the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and
make-ssh-known-hosts. The main program for each of these is in a .c
file with the same name.
There are some subsystems/abstractions that are used by a number of
these programs.
Buffer manipulation routines
- These provide an arbitrary size buffer, where data can be appended.
Data can be consumed from either end. The code is used heavily
throughout ssh. The buffer manipulation functions are in
sshbuf*.c (header sshbuf.h).
Compression Library
- Ssh uses the GNU GZIP compression library (ZLIB).
Encryption/Decryption
- Ssh contains several encryption algorithms. These are all
accessed through the cipher.h interface. The interface code is
- in cipher.c, and the implementations are in libc.
+ in cipher.c, and the implementations are either in libc or
+ LibreSSL.
Multiple Precision Integer Library
- - Uses the SSLeay BIGNUM sublibrary.
+ - Uses the LibreSSL BIGNUM sublibrary.
Random Numbers
- Uses arc4random() and such.
RSA key generation, encryption, decryption
- Ssh uses the RSA routines in libssl.
RSA key files
- RSA keys are stored in files with a special format. The code to
read/write these files is in authfile.c. The files are normally
encrypted with a passphrase. The functions to read passphrases
are in readpass.c (the same code is used to read passwords).
Binary packet protocol
- The ssh binary packet protocol is implemented in packet.c. The
code in packet.c does not concern itself with packet types or their
execution; it contains code to build packets, to receive them and
extract data from them, and the code to compress and/or encrypt
packets.
- The code in packet.c calls the buffer manipulation routines
(buffer.c, bufaux.c), compression routines (zlib), and the
encryption routines.
X11, TCP/IP, and Agent forwarding
- Code for various types of channel forwarding is in channels.c.
The file defines a generic framework for arbitrary communication
channels inside the secure channel, and uses this framework to
implement X11 forwarding, TCP/IP forwarding, and authentication
agent forwarding.
The new, Protocol 1.5, channel close implementation is in nchan.c
Authentication agent
- Code to communicate with the authentication agent is in authfd.c.
Authentication methods
- Code for various authentication methods resides in auth-*.c
(auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This
code is linked into the server. The routines also manipulate
known hosts files using code in hostfile.c. Code in canohost.c
is used to retrieve the canonical host name of the remote host.
Code in match.c is used to match host names.
- In the client end, authentication code is in sshconnect.c. It
reads Passwords/passphrases using code in readpass.c. It reads
RSA key files with authfile.c. It communicates the
authentication agent using authfd.c.
The ssh client
- The client main program is in ssh.c. It first parses arguments
and reads configuration (readconf.c), then calls ssh_connect (in
sshconnect.c) to open a connection to the server (possibly via a
proxy), and performs authentication (ssh_login in sshconnect.c).
It then makes any pty, forwarding, etc. requests. It may call
code in ttymodes.c to encode current tty modes. Finally it
calls client_loop in clientloop.c. This does the real work for
the session.
Pseudo-tty manipulation and tty modes
- Code to allocate and use a pseudo tty is in pty.c. Code to
encode and set terminal modes is in ttymodes.c.
Logging in (updating utmp, lastlog, etc.)
- The code to do things that are done when a user logs in are in
login.c. This includes things such as updating the utmp, wtmp,
and lastlog files. Some of the code is in sshd.c.
Writing to the system log and terminal
- The programs use the functions fatal(), log(), debug(), error()
in many places to write messages to system log or user's
terminal. The implementation that logs to system log is in
log-server.c; it is used in the server program. The other
programs use an implementation that sends output to stderr; it
is in log-client.c. The definitions are in ssh.h.
The sshd server (daemon)
- The sshd daemon starts by processing arguments and reading the
configuration file (servconf.c). It then reads the host key,
starts listening for connections, and generates the server key.
The server key will be regenerated every hour by an alarm.
- When the server receives a connection, it forks, disables the
regeneration alarm, and starts communicating with the client.
They first perform identification string exchange, then
negotiate encryption, then perform authentication, preparatory
operations, and finally the server enters the normal session
mode by calling server_loop in serverloop.c. This does the real
work, calling functions in other modules.
- The code for the server is in sshd.c. It contains a lot of
stuff, including:
- server main program
- waiting for connections
- processing new connection
- authentication
- preparatory operations
- building up the execution environment for the user program
- starting the user program.
Auxiliary files
- There are several other files in the distribution that contain
various auxiliary routines:
ssh.h the main header file for ssh (various definitions)
uidswap.c uid-swapping
xmalloc.c "safe" malloc routines
-$OpenBSD: OVERVIEW,v 1.14 2018/07/27 03:55:22 dtucker Exp $
+$OpenBSD: OVERVIEW,v 1.15 2018/10/23 05:56:35 djm Exp $
diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys
index 11363fdc370e..48338e671cc5 100644
--- a/PROTOCOL.certkeys
+++ b/PROTOCOL.certkeys
@@ -1,306 +1,307 @@
This document describes a simple public-key certificate authentication
system for use by SSH.
Background
----------
The SSH protocol currently supports a simple public key authentication
mechanism. Unlike other public key implementations, SSH eschews the use
of X.509 certificates and uses raw keys. This approach has some benefits
relating to simplicity of configuration and minimisation of attack
surface, but it does not support the important use-cases of centrally
managed, passwordless authentication and centrally certified host keys.
These protocol extensions build on the simple public key authentication
system already in SSH to allow certificate-based authentication. The
certificates used are not traditional X.509 certificates, with numerous
options and complex encoding rules, but something rather more minimal: a
key, some identity information and usage options that have been signed
with some other trusted key.
A sshd server may be configured to allow authentication via certified
keys, by extending the existing ~/.ssh/authorized_keys mechanism to
allow specification of certification authority keys in addition to
raw user keys. The ssh client will support automatic verification of
acceptance of certified host keys, by adding a similar ability to
specify CA keys in ~/.ssh/known_hosts.
All certificate types include certification information along with the
public key that is used to sign challenges. In OpenSSH, ssh-keygen
performs the CA signing operation.
Certified keys are represented using new key types:
ssh-rsa-cert-v01@openssh.com
ssh-dss-cert-v01@openssh.com
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384-cert-v01@openssh.com
ecdsa-sha2-nistp521-cert-v01@openssh.com
+ ssh-ed25519-cert-v01@openssh.com
Two additional types exist for RSA certificates to force use of
SHA-2 signatures (SHA-256 and SHA-512 respectively):
rsa-sha2-256-cert-v01@openssh.com
rsa-sha2-512-cert-v01@openssh.com
These RSA/SHA-2 types should not appear in keys at rest or transmitted
on their wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms
field or in the "public key algorithm name" field of a "publickey"
SSH_USERAUTH_REQUEST to indicate that the signature will use the
specified algorithm.
Protocol extensions
-------------------
The SSH wire protocol includes several extensibility mechanisms.
These modifications shall take advantage of namespaced public key
algorithm names to add support for certificate authentication without
breaking the protocol - implementations that do not support the
extensions will simply ignore them.
Authentication using the new key formats described below proceeds
using the existing SSH "publickey" authentication method described
in RFC4252 section 7.
New public key formats
----------------------
The certificate key types take a similar high-level format (note: data
types and encoding are as per RFC4251 section 5). The serialised wire
encoding of these certificates is also used for storing them on disk.
#define SSH_CERT_TYPE_USER 1
#define SSH_CERT_TYPE_HOST 2
RSA certificate
string "ssh-rsa-cert-v01@openssh.com"
string nonce
mpint e
mpint n
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
DSA certificate
string "ssh-dss-cert-v01@openssh.com"
string nonce
mpint p
mpint q
mpint g
mpint y
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
ECDSA certificate
string "ecdsa-sha2-nistp256-cert-v01@openssh.com" |
"ecdsa-sha2-nistp384-cert-v01@openssh.com" |
"ecdsa-sha2-nistp521-cert-v01@openssh.com"
string nonce
string curve
string public_key
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
ED25519 certificate
string "ssh-ed25519-cert-v01@openssh.com"
string nonce
string pk
uint64 serial
uint32 type
string key id
string valid principals
uint64 valid after
uint64 valid before
string critical options
string extensions
string reserved
string signature key
string signature
The nonce field is a CA-provided random bitstring of arbitrary length
(but typically 16 or 32 bytes) included to make attacks that depend on
inducing collisions in the signature hash infeasible.
e and n are the RSA exponent and public modulus respectively.
p, q, g, y are the DSA parameters as described in FIPS-186-2.
curve and public key are respectively the ECDSA "[identifier]" and "Q"
defined in section 3.1 of RFC5656.
pk is the encoded Ed25519 public key as defined by
draft-josefsson-eddsa-ed25519-03.
serial is an optional certificate serial number set by the CA to
provide an abbreviated way to refer to certificates from that CA.
If a CA does not wish to number its certificates it must set this
field to zero.
type specifies whether this certificate is for identification of a user
or a host using a SSH_CERT_TYPE_... value.
key id is a free-form text field that is filled in by the CA at the time
of signing; the intention is that the contents of this field are used to
identify the identity principal in log messages.
"valid principals" is a string containing zero or more principals as
strings packed inside it. These principals list the names for which this
certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and
usernames for SSH_CERT_TYPE_USER certificates. As a special case, a
zero-length "valid principals" field means the certificate is valid for
any principal of the specified type.
"valid after" and "valid before" specify a validity period for the
certificate. Each represents a time in seconds since 1970-01-01
00:00:00. A certificate is considered valid if:
valid after <= current time < valid before
critical options is a set of zero or more key options encoded as
below. All such options are "critical" in the sense that an implementation
must refuse to authorise a key that has an unrecognised option.
extensions is a set of zero or more optional extensions. These extensions
are not critical, and an implementation that encounters one that it does
not recognise may safely ignore it.
Generally, critical options are used to control features that restrict
access where extensions are used to enable features that grant access.
This ensures that certificates containing unknown restrictions do not
inadvertently grant access while allowing new protocol features to be
enabled via extensions without breaking certificates' backwards
compatibility.
The reserved field is currently unused and is ignored in this version of
the protocol.
The signature key field contains the CA key used to sign the
certificate. The valid key types for CA keys are ssh-rsa,
ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256,
ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where
the signature key type is a certificate type itself are NOT supported.
Note that it is possible for a RSA certificate key to be signed by a
Ed25519 or ECDSA CA key and vice-versa.
signature is computed over all preceding fields from the initial string
up to, and including the signature key. Signatures are computed and
encoded according to the rules defined for the CA's public key algorithm
(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA
types), and draft-josefsson-eddsa-ed25519-03 for Ed25519.
Critical options
----------------
The critical options section of the certificate specifies zero or more
options on the certificates validity. The format of this field
is a sequence of zero or more tuples:
string name
string data
Options must be lexically ordered by "name" if they appear in the
sequence. Each named option may only appear once in a certificate.
The name field identifies the option and the data field encodes
option-specific information (see below). All options are
"critical", if an implementation does not recognise a option
then the validating party should refuse to accept the certificate.
Custom options should append the originating author or organisation's
domain name to the option name, e.g. "my-option@example.com".
No critical options are defined for host certificates at present. The
supported user certificate options and the contents and structure of
their data fields are:
Name Format Description
-----------------------------------------------------------------------------
force-command string Specifies a command that is executed
(replacing any the user specified on the
ssh command-line) whenever this key is
used for authentication.
source-address string Comma-separated list of source addresses
from which this certificate is accepted
for authentication. Addresses are
specified in CIDR format (nn.nn.nn.nn/nn
or hhhh::hhhh/nn).
If this option is not present then
certificates may be presented from any
source address.
Extensions
----------
The extensions section of the certificate specifies zero or more
non-critical certificate extensions. The encoding and ordering of
extensions in this field is identical to that of the critical options,
as is the requirement that each name appear only once.
If an implementation does not recognise an extension, then it should
ignore it.
Custom options should append the originating author or organisation's
domain name to the option name, e.g. "my-option@example.com".
No extensions are defined for host certificates at present. The
supported user certificate extensions and the contents and structure of
their data fields are:
Name Format Description
-----------------------------------------------------------------------------
permit-X11-forwarding empty Flag indicating that X11 forwarding
should be permitted. X11 forwarding will
be refused if this option is absent.
permit-agent-forwarding empty Flag indicating that agent forwarding
should be allowed. Agent forwarding
must not be permitted unless this
option is present.
permit-port-forwarding empty Flag indicating that port-forwarding
should be allowed. If this option is
not present then no port forwarding will
be allowed.
permit-pty empty Flag indicating that PTY allocation
should be permitted. In the absence of
this option PTY allocation will be
disabled.
permit-user-rc empty Flag indicating that execution of
~/.ssh/rc should be permitted. Execution
of this script will not be permitted if
this option is not present.
-$OpenBSD: PROTOCOL.certkeys,v 1.15 2018/07/03 11:39:54 djm Exp $
+$OpenBSD: PROTOCOL.certkeys,v 1.16 2018/10/26 01:23:03 djm Exp $
diff --git a/README b/README
index 05916459c08b..77cb0ef3ad52 100644
--- a/README
+++ b/README
@@ -1,62 +1,62 @@
-See https://www.openssh.com/releasenotes.html#7.9p1 for the release notes.
+See https://www.openssh.com/releasenotes.html#8.0p1 for the release notes.
Please read https://www.openssh.com/report.html for bug reporting
instructions and note that we do not use Github for bug reporting or
patch/pull-request management.
This is the port of OpenBSD's excellent OpenSSH[0] to Linux and other
Unices.
OpenSSH is based on the last free version of Tatu Ylonen's sample
implementation with all patent-encumbered algorithms removed (to
external libraries), all known security bugs fixed, new features
reintroduced and many other clean-ups. OpenSSH has been created by
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt,
and Dug Song. It has a homepage at https://www.openssh.com/
This port consists of the re-introduction of autoconf support, PAM
support, EGD[1]/PRNGD[2] support and replacements for OpenBSD library
functions that are (regrettably) absent from other unices. This port
has been best tested on AIX, Cygwin, HP-UX, Linux, MacOS/X,
FreeBSD, NetBSD, OpenBSD, OpenServer, Solaris and UnixWare.
This version actively tracks changes in the OpenBSD CVS repository.
The PAM support is now more functional than the popular packages of
commercial ssh-1.2.x. It checks "account" and "session" modules for
all logins, not just when using password authentication.
OpenSSH depends on Zlib[3], OpenSSL[4], and optionally PAM[5] and
libedit[6]
There is now several mailing lists for this port of OpenSSH. Please
refer to https://www.openssh.com/list.html for details on how to join.
Please send bug reports and patches to the mailing list
openssh-unix-dev@mindrot.org. The list is open to posting by unsubscribed
users. Code contribution are welcomed, but please follow the OpenBSD
style guidelines[7].
Please refer to the INSTALL document for information on how to install
OpenSSH on your system.
Damien Miller <djm@mindrot.org>
Miscellania -
This version of OpenSSH is based upon code retrieved from the OpenBSD
CVS repository which in turn was based on the last free sample
implementation released by Tatu Ylonen.
References -
[0] https://www.openssh.com/
[1] http://www.lothar.com/tech/crypto/
[2] http://prngd.sourceforge.net/
[3] https://www.zlib.net/
[4] https://www.openssl.org/
[5] https://www.openpam.org
https://www.kernel.org/pub/linux/libs/pam/
(PAM also is standard on Solaris and HP-UX 11)
[6] https://thrysoee.dk/editline/ (portable version)
[7] https://man.openbsd.org/style.9
diff --git a/README.md b/README.md
new file mode 100644
index 000000000000..4e2624161b93
--- /dev/null
+++ b/README.md
@@ -0,0 +1,74 @@
+# Portable OpenSSH
+
+OpenSSH is a complete implementation of the SSH protocol (version 2) for secure remote login, command execution and file transfer. It includes a client ``ssh`` and server ``sshd``, file transfer utilities ``scp`` and ``sftp`` as well as tools for key generation (``ssh-keygen``), run-time key storage (``ssh-agent``) and a number of supporting programs.
+
+This is a port of OpenBSD's [OpenSSH](https://openssh.com) to most Unix-like operating systems, including Linux, OS X and Cygwin. Portable OpenSSH polyfills OpenBSD APIs that are not available elsewhere, adds sshd sandboxing for more operating systems and includes support for OS-native authentication and auditing (e.g. using PAM).
+
+## Documentation
+
+The official documentation for OpenSSH are the man pages for each tool:
+
+* [ssh(1)](https://man.openbsd.org/ssh.1)
+* [sshd(8)](https://man.openbsd.org/sshd.8)
+* [ssh-keygen(1)](https://man.openbsd.org/ssh-keygen.1)
+* [ssh-agent(1)](https://man.openbsd.org/ssh-agent.1)
+* [scp(1)](https://man.openbsd.org/scp.1)
+* [sftp(1)](https://man.openbsd.org/sftp.1)
+* [ssh-keyscan(8)](https://man.openbsd.org/ssh-keyscan.8)
+* [sftp-server(8)](https://man.openbsd.org/sftp-server.8)
+
+## Stable Releases
+
+Stable release tarballs are available from a number of [download mirrors](https://www.openssh.com/portable.html#downloads). We recommend the use of a stable release for most users. Please read the [release notes](https://www.openssh.com/releasenotes.html) for details of recent changes and potential incompatibilities.
+
+## Building Portable OpenSSH
+
+### Dependencies
+
+Portable OpenSSH is built using autoconf and make. It requires a working C compiler, standard library and headers, as well as [zlib](https://www.zlib.net/) and ``libcrypto`` from either [LibreSSL](https://www.libressl.org/) or [OpenSSL](https://www.openssl.org) to build. Certain platforms and build-time options may require additional dependencies.
+
+### Building a release
+
+Releases include a pre-built copy of the ``configure`` script and may be built using:
+
+```
+tar zxvf openssh-X.Y.tar.gz
+cd openssh
+./configure # [options]
+make && make tests
+```
+
+See the [Build-time Customisation](#build-time-customisation) section below for configure options. If you plan on installing OpenSSH to your system, then you will usually want to specify destination paths.
+
+### Building from git
+
+If building from git, you'll need [autoconf](https://www.gnu.org/software/autoconf/) installed to build the ``configure`` script. The following commands will check out and build portable OpenSSH from git:
+
+```
+git clone https://github.com/openssh/openssh-portable # or https://anongit.mindrot.org/openssh.git
+cd openssh-portable
+autoreconf
+./configure
+make && make tests
+```
+
+### Build-time Customisation
+
+There are many build-time customisation options available. All Autoconf destination path flags (e.g. ``--prefix``) are supported (and are usually required if you want to install OpenSSH).
+
+For a full list of available flags, run ``configure --help`` but a few of the more frequently-used ones are described below. Some of these flags will require additional libraries and/or headers be installed.
+
+Flag | Meaning
+--- | ---
+``--with-pam`` | Enable [PAM](https://en.wikipedia.org/wiki/Pluggable_authentication_module) support. [OpenPAM](https://www.openpam.org/), [Linux PAM](http://www.linux-pam.org/) and Solaris PAM are supported.
+``--with-libedit`` | Enable [libedit](https://www.thrysoee.dk/editline/) support for sftp.
+``--with-kerberos5`` | Enable Kerberos/GSSAPI support. Both [Heimdal](https://www.h5l.org/) and [MIT](https://web.mit.edu/kerberos/) Kerberos implementations are supported.
+``--with-selinux`` | Enable [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux) support.
+
+## Development
+
+Portable OpenSSH development is discussed on the [openssh-unix-dev mailing list](https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev) ([archive mirror](https://marc.info/?l=openssh-unix-dev)). Bugs and feature requests are tracked on our [Bugzilla](https://bugzilla.mindrot.org/).
+
+## Reporting bugs
+
+_Non-security_ bugs may be reported to the developers via [Bugzilla](https://bugzilla.mindrot.org/) or via the mailing list above. Security bugs should be reported to [openssh@openssh.com](mailto:openssh.openssh.com).
diff --git a/atomicio.c b/atomicio.c
index f854a06f5f50..e00c9f0d4e22 100644
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,170 +1,180 @@
-/* $OpenBSD: atomicio.c,v 1.28 2016/07/27 23:18:12 djm Exp $ */
+/* $OpenBSD: atomicio.c,v 1.30 2019/01/24 02:42:23 dtucker Exp $ */
/*
* Copyright (c) 2006 Damien Miller. All rights reserved.
* Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
* Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/param.h>
#include <sys/uio.h>
#include <errno.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
#endif
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "atomicio.h"
/*
* ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
int (*cb)(void *, size_t), void *cb_arg)
{
char *s = _s;
size_t pos = 0;
ssize_t res;
struct pollfd pfd;
-#ifndef BROKEN_READ_COMPARISON
pfd.fd = fd;
+#ifndef BROKEN_READ_COMPARISON
pfd.events = f == read ? POLLIN : POLLOUT;
+#else
+ pfd.events = POLLIN|POLLOUT;
#endif
while (n > pos) {
res = (f) (fd, s + pos, n - pos);
switch (res) {
case -1:
- if (errno == EINTR)
+ if (errno == EINTR) {
+ /* possible SIGALARM, update callback */
+ if (cb != NULL && cb(cb_arg, 0) == -1) {
+ errno = EINTR;
+ return pos;
+ }
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
-#ifndef BROKEN_READ_COMPARISON
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
(void)poll(&pfd, 1, -1);
-#endif
continue;
}
return 0;
case 0:
errno = EPIPE;
return pos;
default:
pos += (size_t)res;
if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
errno = EINTR;
return pos;
}
}
}
return pos;
}
size_t
atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
{
return atomicio6(f, fd, _s, n, NULL, NULL);
}
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt,
int (*cb)(void *, size_t), void *cb_arg)
{
size_t pos = 0, rem;
ssize_t res;
struct iovec iov_array[IOV_MAX], *iov = iov_array;
struct pollfd pfd;
if (iovcnt < 0 || iovcnt > IOV_MAX) {
errno = EINVAL;
return 0;
}
/* Make a copy of the iov array because we may modify it below */
memcpy(iov, _iov, (size_t)iovcnt * sizeof(*_iov));
-#ifndef BROKEN_READV_COMPARISON
pfd.fd = fd;
+#ifndef BROKEN_READV_COMPARISON
pfd.events = f == readv ? POLLIN : POLLOUT;
+#else
+ pfd.events = POLLIN|POLLOUT;
#endif
for (; iovcnt > 0 && iov[0].iov_len > 0;) {
res = (f) (fd, iov, iovcnt);
switch (res) {
case -1:
- if (errno == EINTR)
+ if (errno == EINTR) {
+ /* possible SIGALARM, update callback */
+ if (cb != NULL && cb(cb_arg, 0) == -1) {
+ errno = EINTR;
+ return pos;
+ }
continue;
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
-#ifndef BROKEN_READV_COMPARISON
+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
(void)poll(&pfd, 1, -1);
-#endif
continue;
}
return 0;
case 0:
errno = EPIPE;
return pos;
default:
rem = (size_t)res;
pos += rem;
/* skip completed iov entries */
while (iovcnt > 0 && rem >= iov[0].iov_len) {
rem -= iov[0].iov_len;
iov++;
iovcnt--;
}
/* This shouldn't happen... */
if (rem > 0 && (iovcnt <= 0 || rem > iov[0].iov_len)) {
errno = EFAULT;
return 0;
}
if (iovcnt == 0)
break;
/* update pointer in partially complete iov */
iov[0].iov_base = ((char *)iov[0].iov_base) + rem;
iov[0].iov_len -= rem;
}
if (cb != NULL && cb(cb_arg, (size_t)res) == -1) {
errno = EINTR;
return pos;
}
}
return pos;
}
size_t
atomiciov(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt)
{
return atomiciov6(f, fd, _iov, iovcnt, NULL, NULL);
}
diff --git a/atomicio.h b/atomicio.h
index 0d728ac86ea9..8b3cc6e211bd 100644
--- a/atomicio.h
+++ b/atomicio.h
@@ -1,51 +1,53 @@
-/* $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) 1995,1999 Theo de Raadt. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ATOMICIO_H
#define _ATOMICIO_H
+struct iovec;
+
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
size_t
atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
int (*cb)(void *, size_t), void *);
size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
#define vwrite (ssize_t (*)(int, void *, size_t))write
/*
* ensure all of data on socket comes through. f==readv || f==writev
*/
size_t
atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
const struct iovec *_iov, int iovcnt, int (*cb)(void *, size_t), void *);
size_t atomiciov(ssize_t (*)(int, const struct iovec *, int),
int, const struct iovec *, int);
#endif /* _ATOMICIO_H */
diff --git a/audit-bsm.c b/audit-bsm.c
index 1409f69aeb90..0ba16c72c820 100644
--- a/audit-bsm.c
+++ b/audit-bsm.c
@@ -1,454 +1,454 @@
/*
* TODO
*
* - deal with overlap between this and sys_auth_allowed_user
* sys_auth_record_login and record_failed_login.
*/
/*
* Copyright 1988-2002 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* #pragma ident "@(#)bsmaudit.c 1.1 01/09/17 SMI" */
#include "includes.h"
#if defined(USE_BSM_AUDIT)
#include <sys/types.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#ifdef BROKEN_BSM_API
#include <libscf.h>
#endif
#include "ssh.h"
#include "log.h"
#include "hostfile.h"
#include "auth.h"
#include "xmalloc.h"
#ifndef AUE_openssh
# define AUE_openssh 32800
#endif
#include <bsm/audit.h>
#include <bsm/libbsm.h>
#include <bsm/audit_uevents.h>
#include <bsm/audit_record.h>
#include <locale.h>
#if defined(HAVE_GETAUDIT_ADDR)
#define AuditInfoStruct auditinfo_addr
#define AuditInfoTermID au_tid_addr_t
#define SetAuditFunc(a,b) setaudit_addr((a),(b))
#define SetAuditFuncText "setaudit_addr"
#define AUToSubjectFunc au_to_subject_ex
#define AUToReturnFunc(a,b) au_to_return32((a), (int32_t)(b))
#else
#define AuditInfoStruct auditinfo
#define AuditInfoTermID au_tid_t
#define SetAuditFunc(a,b) setaudit(a)
#define SetAuditFuncText "setaudit"
#define AUToSubjectFunc au_to_subject
#define AUToReturnFunc(a,b) au_to_return((a), (u_int)(b))
#endif
#ifndef cannot_audit
extern int cannot_audit(int);
#endif
extern void aug_init(void);
extern void aug_save_auid(au_id_t);
extern void aug_save_uid(uid_t);
extern void aug_save_euid(uid_t);
extern void aug_save_gid(gid_t);
extern void aug_save_egid(gid_t);
extern void aug_save_pid(pid_t);
extern void aug_save_asid(au_asid_t);
extern void aug_save_tid(dev_t, unsigned int);
extern void aug_save_tid_ex(dev_t, u_int32_t *, u_int32_t);
extern int aug_save_me(void);
extern int aug_save_namask(void);
extern void aug_save_event(au_event_t);
extern void aug_save_sorf(int);
extern void aug_save_text(char *);
extern void aug_save_text1(char *);
extern void aug_save_text2(char *);
extern void aug_save_na(int);
extern void aug_save_user(char *);
extern void aug_save_path(char *);
extern int aug_save_policy(void);
extern void aug_save_afunc(int (*)(int));
extern int aug_audit(void);
extern int aug_na_selected(void);
extern int aug_selected(void);
extern int aug_daemon_session(void);
#ifndef HAVE_GETTEXT
# define gettext(a) (a)
#endif
extern Authctxt *the_authctxt;
static AuditInfoTermID ssh_bsm_tid;
#ifdef BROKEN_BSM_API
/* For some reason this constant is no longer defined
in Solaris 11. */
#define BSM_TEXTBUFSZ 256
#endif
/* Below is the low-level BSM interface code */
/*
* aug_get_machine is only required on IPv6 capable machines, we use a
* different mechanism in audit_connection_from() for IPv4-only machines.
* getaudit_addr() is only present on IPv6 capable machines.
*/
#if defined(HAVE_AUG_GET_MACHINE) || !defined(HAVE_GETAUDIT_ADDR)
extern int aug_get_machine(char *, u_int32_t *, u_int32_t *);
#else
static int
aug_get_machine(char *host, u_int32_t *addr, u_int32_t *type)
{
struct addrinfo *ai;
struct sockaddr_in *in4;
struct sockaddr_in6 *in6;
int ret = 0, r;
if ((r = getaddrinfo(host, NULL, NULL, &ai)) != 0) {
error("BSM audit: getaddrinfo failed for %.100s: %.100s", host,
r == EAI_SYSTEM ? strerror(errno) : gai_strerror(r));
return -1;
}
switch (ai->ai_family) {
case AF_INET:
in4 = (struct sockaddr_in *)ai->ai_addr;
*type = AU_IPv4;
memcpy(addr, &in4->sin_addr, sizeof(struct in_addr));
break;
#ifdef AU_IPv6
case AF_INET6:
in6 = (struct sockaddr_in6 *)ai->ai_addr;
*type = AU_IPv6;
memcpy(addr, &in6->sin6_addr, sizeof(struct in6_addr));
break;
#endif
default:
error("BSM audit: unknown address family for %.100s: %d",
host, ai->ai_family);
ret = -1;
}
freeaddrinfo(ai);
return ret;
}
#endif
#ifdef BROKEN_BSM_API
/*
In Solaris 11 the audit daemon has been moved to SMF. In the process
they simply dropped getacna() from the API, since it read from a now
non-existent config file. This function re-implements getacna() to
read from the SMF repository instead.
*/
int
getacna(char *auditstring, int len)
{
scf_handle_t *handle = NULL;
scf_property_t *property = NULL;
scf_value_t *value = NULL;
int ret = 0;
handle = scf_handle_create(SCF_VERSION);
if (handle == NULL)
return -2; /* The man page for getacna on Solaris 10 states
we should return -2 in case of error and set
errno to indicate the error. We don't bother
with errno here, though, since the only use
of this function below doesn't check for errors
anyway.
*/
ret = scf_handle_bind(handle);
if (ret == -1)
return -2;
property = scf_property_create(handle);
if (property == NULL)
return -2;
ret = scf_handle_decode_fmri(handle,
"svc:/system/auditd:default/:properties/preselection/naflags",
NULL, NULL, NULL, NULL, property, 0);
if (ret == -1)
return -2;
value = scf_value_create(handle);
if (value == NULL)
return -2;
ret = scf_property_get_value(property, value);
if (ret == -1)
return -2;
ret = scf_value_get_astring(value, auditstring, len);
if (ret == -1)
return -2;
scf_value_destroy(value);
scf_property_destroy(property);
scf_handle_destroy(handle);
return 0;
}
#endif
/*
* Check if the specified event is selected (enabled) for auditing.
* Returns 1 if the event is selected, 0 if not and -1 on failure.
*/
static int
selected(char *username, uid_t uid, au_event_t event, int sf)
{
int rc, sorf;
char naflags[512];
struct au_mask mask;
mask.am_success = mask.am_failure = 0;
if (uid < 0) {
/* get flags for non-attributable (to a real user) events */
rc = getacna(naflags, sizeof(naflags));
if (rc == 0)
(void) getauditflagsbin(naflags, &mask);
} else
rc = au_user_mask(username, &mask);
sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
return(au_preselect(event, &mask, sorf, AU_PRS_REREAD));
}
static void
bsm_audit_record(int typ, char *string, au_event_t event_no)
{
int ad, rc, sel;
uid_t uid = -1;
gid_t gid = -1;
pid_t pid = getpid();
AuditInfoTermID tid = ssh_bsm_tid;
if (the_authctxt != NULL && the_authctxt->valid) {
uid = the_authctxt->pw->pw_uid;
gid = the_authctxt->pw->pw_gid;
}
rc = (typ == 0) ? 0 : -1;
sel = selected(the_authctxt->user, uid, event_no, rc);
debug3("BSM audit: typ %d rc %d \"%s\"", typ, rc, string);
if (!sel)
return; /* audit event does not match mask, do not write */
debug3("BSM audit: writing audit new record");
ad = au_open();
(void) au_write(ad, AUToSubjectFunc(uid, uid, gid, uid, gid,
pid, pid, &tid));
(void) au_write(ad, au_to_text(string));
(void) au_write(ad, AUToReturnFunc(typ, rc));
#ifdef BROKEN_BSM_API
/* The last argument is the event modifier flags. For
some seemingly undocumented reason it was added in
Solaris 11. */
rc = au_close(ad, AU_TO_WRITE, event_no, 0);
#else
rc = au_close(ad, AU_TO_WRITE, event_no);
#endif
if (rc < 0)
error("BSM audit: %s failed to write \"%s\" record: %s",
__func__, string, strerror(errno));
}
static void
bsm_audit_session_setup(void)
{
int rc;
struct AuditInfoStruct info;
au_mask_t mask;
if (the_authctxt == NULL) {
error("BSM audit: session setup internal error (NULL ctxt)");
return;
}
if (the_authctxt->valid)
info.ai_auid = the_authctxt->pw->pw_uid;
else
info.ai_auid = -1;
info.ai_asid = getpid();
mask.am_success = 0;
mask.am_failure = 0;
(void) au_user_mask(the_authctxt->user, &mask);
info.ai_mask.am_success = mask.am_success;
info.ai_mask.am_failure = mask.am_failure;
info.ai_termid = ssh_bsm_tid;
rc = SetAuditFunc(&info, sizeof(info));
if (rc < 0)
error("BSM audit: %s: %s failed: %s", __func__,
SetAuditFuncText, strerror(errno));
}
static void
bsm_audit_bad_login(const char *what)
{
char textbuf[BSM_TEXTBUFSZ];
if (the_authctxt->valid) {
(void) snprintf(textbuf, sizeof (textbuf),
gettext("invalid %s for user %s"),
what, the_authctxt->user);
bsm_audit_record(4, textbuf, AUE_openssh);
} else {
(void) snprintf(textbuf, sizeof (textbuf),
gettext("invalid user name \"%s\""),
the_authctxt->user);
bsm_audit_record(3, textbuf, AUE_openssh);
}
}
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
AuditInfoTermID *tid = &ssh_bsm_tid;
char buf[1024];
if (cannot_audit(0))
return;
debug3("BSM audit: connection from %.100s port %d", host, port);
/* populate our terminal id structure */
#if defined(HAVE_GETAUDIT_ADDR)
tid->at_port = (dev_t)port;
aug_get_machine((char *)host, &(tid->at_addr[0]), &(tid->at_type));
snprintf(buf, sizeof(buf), "%08x %08x %08x %08x", tid->at_addr[0],
tid->at_addr[1], tid->at_addr[2], tid->at_addr[3]);
debug3("BSM audit: iptype %d machine ID %s", (int)tid->at_type, buf);
#else
/* this is used on IPv4-only machines */
tid->port = (dev_t)port;
tid->machine = inet_addr(host);
snprintf(buf, sizeof(buf), "%08x", tid->machine);
debug3("BSM audit: machine ID %s", buf);
#endif
}
void
audit_run_command(const char *command)
{
/* not implemented */
}
void
audit_session_open(struct logininfo *li)
{
/* not implemented */
}
void
audit_session_close(struct logininfo *li)
{
/* not implemented */
}
void
-audit_event(ssh_audit_event_t event)
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
char textbuf[BSM_TEXTBUFSZ];
static int logged_in = 0;
const char *user = the_authctxt ? the_authctxt->user : "(unknown user)";
if (cannot_audit(0))
return;
switch(event) {
case SSH_AUTH_SUCCESS:
logged_in = 1;
bsm_audit_session_setup();
snprintf(textbuf, sizeof(textbuf),
gettext("successful login %s"), user);
bsm_audit_record(0, textbuf, AUE_openssh);
break;
case SSH_CONNECTION_CLOSE:
/*
* We can also get a close event if the user attempted auth
* but never succeeded.
*/
if (logged_in) {
snprintf(textbuf, sizeof(textbuf),
gettext("sshd logout %s"), the_authctxt->user);
bsm_audit_record(0, textbuf, AUE_logout);
} else {
debug("%s: connection closed without authentication",
__func__);
}
break;
case SSH_NOLOGIN:
bsm_audit_record(1,
gettext("logins disabled by /etc/nologin"), AUE_openssh);
break;
case SSH_LOGIN_EXCEED_MAXTRIES:
snprintf(textbuf, sizeof(textbuf),
gettext("too many tries for user %s"), the_authctxt->user);
bsm_audit_record(1, textbuf, AUE_openssh);
break;
case SSH_LOGIN_ROOT_DENIED:
bsm_audit_record(2, gettext("not_console"), AUE_openssh);
break;
case SSH_AUTH_FAIL_PASSWD:
bsm_audit_bad_login("password");
break;
case SSH_AUTH_FAIL_KBDINT:
bsm_audit_bad_login("interactive password entry");
break;
default:
debug("%s: unhandled event %d", __func__, event);
}
}
#endif /* BSM */
diff --git a/audit-linux.c b/audit-linux.c
index 136ed76bbe4b..3fcbe5c53ef9 100644
--- a/audit-linux.c
+++ b/audit-linux.c
@@ -1,126 +1,124 @@
/*
* Copyright 2010 Red Hat, Inc. All rights reserved.
* Use is subject to license terms.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Red Hat author: Jan F. Chadima <jchadima@redhat.com>
*/
#include "includes.h"
#if defined(USE_LINUX_AUDIT)
#include <libaudit.h>
#include <unistd.h>
#include <string.h>
#include "log.h"
#include "audit.h"
#include "canohost.h"
#include "packet.h"
const char *audit_username(void);
int
linux_audit_record_event(int uid, const char *username, const char *hostname,
const char *ip, const char *ttyn, int success)
{
int audit_fd, rc, saved_errno;
if ((audit_fd = audit_open()) < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
return 1; /* No audit support in kernel */
else
return 0; /* Must prevent login */
}
rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
NULL, "login", username ? username : "(unknown)",
username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
close(audit_fd);
/*
* Do not report error if the error is EPERM and sshd is run as non
* root user.
*/
if ((rc == -EPERM) && (geteuid() != 0))
rc = 0;
errno = saved_errno;
return rc >= 0;
}
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
/* not implemented */
}
void
audit_run_command(const char *command)
{
/* not implemented */
}
void
audit_session_open(struct logininfo *li)
{
if (linux_audit_record_event(li->uid, NULL, li->hostname, NULL,
li->line, 1) == 0)
fatal("linux_audit_write_entry failed: %s", strerror(errno));
}
void
audit_session_close(struct logininfo *li)
{
/* not implemented */
}
void
-audit_event(ssh_audit_event_t event)
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
- struct ssh *ssh = active_state; /* XXX */
-
switch(event) {
case SSH_AUTH_SUCCESS:
case SSH_CONNECTION_CLOSE:
case SSH_NOLOGIN:
case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
break;
case SSH_AUTH_FAIL_NONE:
case SSH_AUTH_FAIL_PASSWD:
case SSH_AUTH_FAIL_KBDINT:
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
case SSH_AUTH_FAIL_GSSAPI:
case SSH_INVALID_USER:
linux_audit_record_event(-1, audit_username(), NULL,
ssh_remote_ipaddr(ssh), "sshd", 0);
break;
default:
debug("%s: unhandled event %d", __func__, event);
break;
}
}
#endif /* USE_LINUX_AUDIT */
diff --git a/audit.c b/audit.c
index 33a04376dd6e..dd2f03558fe9 100644
--- a/audit.c
+++ b/audit.c
@@ -1,184 +1,184 @@
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
#include "log.h"
#include "hostfile.h"
#include "auth.h"
/*
* Care must be taken when using this since it WILL NOT be initialized when
* audit_connection_from() is called and MAY NOT be initialized when
* audit_event(CONNECTION_ABANDON) is called. Test for NULL before using.
*/
extern Authctxt *the_authctxt;
/* Maybe add the audit class to struct Authmethod? */
ssh_audit_event_t
audit_classify_auth(const char *method)
{
if (strcmp(method, "none") == 0)
return SSH_AUTH_FAIL_NONE;
else if (strcmp(method, "password") == 0)
return SSH_AUTH_FAIL_PASSWD;
else if (strcmp(method, "publickey") == 0 ||
strcmp(method, "rsa") == 0)
return SSH_AUTH_FAIL_PUBKEY;
else if (strncmp(method, "keyboard-interactive", 20) == 0 ||
strcmp(method, "challenge-response") == 0)
return SSH_AUTH_FAIL_KBDINT;
else if (strcmp(method, "hostbased") == 0 ||
strcmp(method, "rhosts-rsa") == 0)
return SSH_AUTH_FAIL_HOSTBASED;
else if (strcmp(method, "gssapi-with-mic") == 0)
return SSH_AUTH_FAIL_GSSAPI;
else
return SSH_AUDIT_UNKNOWN;
}
/* helper to return supplied username */
const char *
audit_username(void)
{
static const char unknownuser[] = "(unknown user)";
static const char invaliduser[] = "(invalid user)";
if (the_authctxt == NULL || the_authctxt->user == NULL)
return (unknownuser);
if (!the_authctxt->valid)
return (invaliduser);
return (the_authctxt->user);
}
const char *
audit_event_lookup(ssh_audit_event_t ev)
{
int i;
static struct event_lookup_struct {
ssh_audit_event_t event;
const char *name;
} event_lookup[] = {
{SSH_LOGIN_EXCEED_MAXTRIES, "LOGIN_EXCEED_MAXTRIES"},
{SSH_LOGIN_ROOT_DENIED, "LOGIN_ROOT_DENIED"},
{SSH_AUTH_SUCCESS, "AUTH_SUCCESS"},
{SSH_AUTH_FAIL_NONE, "AUTH_FAIL_NONE"},
{SSH_AUTH_FAIL_PASSWD, "AUTH_FAIL_PASSWD"},
{SSH_AUTH_FAIL_KBDINT, "AUTH_FAIL_KBDINT"},
{SSH_AUTH_FAIL_PUBKEY, "AUTH_FAIL_PUBKEY"},
{SSH_AUTH_FAIL_HOSTBASED, "AUTH_FAIL_HOSTBASED"},
{SSH_AUTH_FAIL_GSSAPI, "AUTH_FAIL_GSSAPI"},
{SSH_INVALID_USER, "INVALID_USER"},
{SSH_NOLOGIN, "NOLOGIN"},
{SSH_CONNECTION_CLOSE, "CONNECTION_CLOSE"},
{SSH_CONNECTION_ABANDON, "CONNECTION_ABANDON"},
{SSH_AUDIT_UNKNOWN, "AUDIT_UNKNOWN"}
};
for (i = 0; event_lookup[i].event != SSH_AUDIT_UNKNOWN; i++)
if (event_lookup[i].event == ev)
break;
return(event_lookup[i].name);
}
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
* These get used if SSH_AUDIT_EVENTS is defined but no audit module is enabled.
*/
/*
* Called after a connection has been accepted but before any authentication
* has been attempted.
*/
void
audit_connection_from(const char *host, int port)
{
debug("audit connection from %s port %d euid %d", host, port,
(int)geteuid());
}
/*
* Called when various events occur (see audit.h for a list of possible
* events and what they mean).
*/
void
-audit_event(ssh_audit_event_t event)
+audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
debug("audit event euid %d user %s event %d (%s)", geteuid(),
audit_username(), event, audit_event_lookup(event));
}
/*
* Called when a user session is started. Argument is the tty allocated to
* the session, or NULL if no tty was allocated.
*
* Note that this may be called multiple times if multiple sessions are used
* within a single connection.
*/
void
audit_session_open(struct logininfo *li)
{
const char *t = li->line ? li->line : "(no tty)";
debug("audit session open euid %d user %s tty name %s", geteuid(),
audit_username(), t);
}
/*
* Called when a user session is closed. Argument is the tty allocated to
* the session, or NULL if no tty was allocated.
*
* Note that this may be called multiple times if multiple sessions are used
* within a single connection.
*/
void
audit_session_close(struct logininfo *li)
{
const char *t = li->line ? li->line : "(no tty)";
debug("audit session close euid %d user %s tty name %s", geteuid(),
audit_username(), t);
}
/*
* This will be called when a user runs a non-interactive command. Note that
* it may be called multiple times for a single connection since SSH2 allows
* multiple sessions within a single connection.
*/
void
audit_run_command(const char *command)
{
debug("audit run command euid %d user %s command '%.200s'", geteuid(),
audit_username(), command);
}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff --git a/audit.h b/audit.h
index 0b593666d9e1..38cb5ad31d4a 100644
--- a/audit.h
+++ b/audit.h
@@ -1,55 +1,57 @@
/*
* Copyright (c) 2004, 2005 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SSH_AUDIT_H
# define _SSH_AUDIT_H
#include "loginrec.h"
+struct ssh;
+
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
SSH_LOGIN_ROOT_DENIED,
SSH_AUTH_SUCCESS,
SSH_AUTH_FAIL_NONE,
SSH_AUTH_FAIL_PASSWD,
SSH_AUTH_FAIL_KBDINT, /* keyboard-interactive or challenge-response */
SSH_AUTH_FAIL_PUBKEY, /* ssh2 pubkey or ssh1 rsa */
SSH_AUTH_FAIL_HOSTBASED, /* ssh2 hostbased or ssh1 rhostsrsa */
SSH_AUTH_FAIL_GSSAPI,
SSH_INVALID_USER,
SSH_NOLOGIN, /* denied by /etc/nologin, not implemented */
SSH_CONNECTION_CLOSE, /* closed after attempting auth or session */
SSH_CONNECTION_ABANDON, /* closed without completing auth */
SSH_AUDIT_UNKNOWN
};
typedef enum ssh_audit_event_type ssh_audit_event_t;
void audit_connection_from(const char *, int);
-void audit_event(ssh_audit_event_t);
+void audit_event(struct ssh *, ssh_audit_event_t);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
void audit_run_command(const char *);
ssh_audit_event_t audit_classify_auth(const char *);
#endif /* _SSH_AUDIT_H */
diff --git a/auth-pam.c b/auth-pam.c
index 1dec53e929d9..bde0a8f561f2 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -1,1349 +1,1375 @@
/*-
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed for the FreeBSD Project by ThinkSec AS and
* NAI Labs, the Security Research Division of Network Associates, Inc.
* under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
* DARPA CHATS research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Copyright (c) 2003,2004 Damien Miller <djm@mindrot.org>
* Copyright (c) 2003,2004 Darren Tucker <dtucker@zip.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Based on FreeBSD: src/crypto/openssh/auth2-pam-freebsd.c,v 1.11 2003/03/31 13:48:18 des */
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#ifdef USE_PAM
#if defined(HAVE_SECURITY_PAM_APPL_H)
#include <security/pam_appl.h>
#elif defined (HAVE_PAM_PAM_APPL_H)
#include <pam/pam_appl.h>
#endif
#if !defined(SSHD_PAM_SERVICE)
extern char *__progname;
# define SSHD_PAM_SERVICE __progname
#endif
/* OpenGroup RFC86.0 and XSSO specify no "const" on arguments */
#ifdef PAM_SUN_CODEBASE
# define sshpam_const /* Solaris, HP-UX, SunOS */
#else
# define sshpam_const const /* LinuxPAM, OpenPAM, AIX */
#endif
/* Ambiguity in spec: is it an array of pointers or a pointer to an array? */
#ifdef PAM_SUN_CODEBASE
# define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member)
#else
# define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member)
#endif
#include "xmalloc.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-pam.h"
#include "canohost.h"
#include "log.h"
#include "msg.h"
#include "packet.h"
#include "misc.h"
#include "servconf.h"
#include "ssh2.h"
#include "auth-options.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
extern ServerOptions options;
extern struct sshbuf *loginmsg;
extern u_int utmp_len;
/* so we don't silently change behaviour */
#ifdef USE_POSIX_THREADS
# error "USE_POSIX_THREADS replaced by UNSUPPORTED_POSIX_THREADS_HACK"
#endif
/*
* Formerly known as USE_POSIX_THREADS, using this is completely unsupported
* and generally a bad idea. Use at own risk and do not expect support if
* this breaks.
*/
#ifdef UNSUPPORTED_POSIX_THREADS_HACK
#include <pthread.h>
/*
* Avoid namespace clash when *not* using pthreads for systems *with*
* pthreads, which unconditionally define pthread_t via sys/types.h
* (e.g. Linux)
*/
typedef pthread_t sp_pthread_t;
#else
typedef pid_t sp_pthread_t;
#define pthread_exit fake_pthread_exit
#define pthread_create fake_pthread_create
#define pthread_cancel fake_pthread_cancel
#define pthread_join fake_pthread_join
#endif
struct pam_ctxt {
sp_pthread_t pam_thread;
int pam_psock;
int pam_csock;
int pam_done;
};
static void sshpam_free_ctx(void *);
static struct pam_ctxt *cleanup_ctxt;
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/*
* Simulate threads with processes.
*/
static int sshpam_thread_status = -1;
static mysig_t sshpam_oldsig;
static void
sshpam_sigchld_handler(int sig)
{
signal(SIGCHLD, SIG_DFL);
if (cleanup_ctxt == NULL)
return; /* handler called after PAM cleanup, shouldn't happen */
if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
<= 0) {
/* PAM thread has not exitted, privsep slave must have */
kill(cleanup_ctxt->pam_thread, SIGTERM);
while (waitpid(cleanup_ctxt->pam_thread,
&sshpam_thread_status, 0) == -1) {
if (errno == EINTR)
continue;
return;
}
}
if (WIFSIGNALED(sshpam_thread_status) &&
WTERMSIG(sshpam_thread_status) == SIGTERM)
return; /* terminated by pthread_cancel */
if (!WIFEXITED(sshpam_thread_status))
sigdie("PAM: authentication thread exited unexpectedly");
if (WEXITSTATUS(sshpam_thread_status) != 0)
sigdie("PAM: authentication thread exited uncleanly");
}
/* ARGSUSED */
static void
pthread_exit(void *value)
{
_exit(0);
}
/* ARGSUSED */
static int
pthread_create(sp_pthread_t *thread, const void *attr,
void *(*thread_start)(void *), void *arg)
{
pid_t pid;
struct pam_ctxt *ctx = arg;
sshpam_thread_status = -1;
switch ((pid = fork())) {
case -1:
error("fork(): %s", strerror(errno));
return (-1);
case 0:
close(ctx->pam_psock);
ctx->pam_psock = -1;
thread_start(arg);
_exit(1);
default:
*thread = pid;
close(ctx->pam_csock);
ctx->pam_csock = -1;
sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler);
return (0);
}
}
static int
pthread_cancel(sp_pthread_t thread)
{
signal(SIGCHLD, sshpam_oldsig);
return (kill(thread, SIGTERM));
}
/* ARGSUSED */
static int
pthread_join(sp_pthread_t thread, void **value)
{
int status;
if (sshpam_thread_status != -1)
return (sshpam_thread_status);
signal(SIGCHLD, sshpam_oldsig);
while (waitpid(thread, &status, 0) == -1) {
if (errno == EINTR)
continue;
fatal("%s: waitpid: %s", __func__, strerror(errno));
}
return (status);
}
#endif
static pam_handle_t *sshpam_handle = NULL;
static int sshpam_err = 0;
static int sshpam_authenticated = 0;
static int sshpam_session_open = 0;
static int sshpam_cred_established = 0;
static int sshpam_account_status = -1;
static int sshpam_maxtries_reached = 0;
static char **sshpam_env = NULL;
static Authctxt *sshpam_authctxt = NULL;
static const char *sshpam_password = NULL;
+static char *sshpam_rhost = NULL;
+static char *sshpam_laddr = NULL;
+static char *sshpam_conninfo = NULL;
/* Some PAM implementations don't implement this */
#ifndef HAVE_PAM_GETENVLIST
static char **
pam_getenvlist(pam_handle_t *pamh)
{
/*
* XXX - If necessary, we can still support envrionment passing
* for platforms without pam_getenvlist by searching for known
* env vars (e.g. KRB5CCNAME) from the PAM environment.
*/
return NULL;
}
#endif
/*
* Some platforms, notably Solaris, do not enforce password complexity
* rules during pam_chauthtok() if the real uid of the calling process
* is 0, on the assumption that it's being called by "passwd" run by root.
* This wraps pam_chauthtok and sets/restore the real uid so PAM will do
* the right thing.
*/
#ifdef SSHPAM_CHAUTHTOK_NEEDS_RUID
static int
sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags)
{
int result;
if (sshpam_authctxt == NULL)
fatal("PAM: sshpam_authctxt not initialized");
if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1)
fatal("%s: setreuid failed: %s", __func__, strerror(errno));
result = pam_chauthtok(pamh, flags);
if (setreuid(0, -1) == -1)
fatal("%s: setreuid failed: %s", __func__, strerror(errno));
return result;
}
# define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b)))
#endif
void
sshpam_password_change_required(int reqd)
{
extern struct sshauthopt *auth_opts;
static int saved_port, saved_agent, saved_x11;
debug3("%s %d", __func__, reqd);
if (sshpam_authctxt == NULL)
fatal("%s: PAM authctxt not initialized", __func__);
sshpam_authctxt->force_pwchange = reqd;
if (reqd) {
saved_port = auth_opts->permit_port_forwarding_flag;
saved_agent = auth_opts->permit_agent_forwarding_flag;
saved_x11 = auth_opts->permit_x11_forwarding_flag;
auth_opts->permit_port_forwarding_flag = 0;
auth_opts->permit_agent_forwarding_flag = 0;
auth_opts->permit_x11_forwarding_flag = 0;
} else {
if (saved_port)
auth_opts->permit_port_forwarding_flag = saved_port;
if (saved_agent)
auth_opts->permit_agent_forwarding_flag = saved_agent;
if (saved_x11)
auth_opts->permit_x11_forwarding_flag = saved_x11;
}
}
/* Import regular and PAM environment from subprocess */
static void
import_environments(struct sshbuf *b)
{
char *env;
u_int n, i, num_env;
int r;
debug3("PAM: %s entering", __func__);
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/* Import variables set by do_pam_account */
if ((r = sshbuf_get_u32(b, &n)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (n > INT_MAX)
fatal("%s: invalid PAM account status %u", __func__, n);
sshpam_account_status = (int)n;
if ((r = sshbuf_get_u32(b, &n)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshpam_password_change_required(n != 0);
/* Import environment from subprocess */
if ((r = sshbuf_get_u32(b, &num_env)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (num_env > 1024)
fatal("%s: received %u environment variables, expected <= 1024",
__func__, num_env);
sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
debug3("PAM: num env strings %d", num_env);
for(i = 0; i < num_env; i++) {
if ((r = sshbuf_get_cstring(b, &(sshpam_env[i]), NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
sshpam_env[num_env] = NULL;
/* Import PAM environment from subprocess */
if ((r = sshbuf_get_u32(b, &num_env)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("PAM: num PAM env strings %d", num_env);
for (i = 0; i < num_env; i++) {
if ((r = sshbuf_get_cstring(b, &env, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifdef HAVE_PAM_PUTENV
/* Errors are not fatal here */
if ((r = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
error("PAM: pam_putenv: %s",
pam_strerror(sshpam_handle, r));
}
#endif
/* XXX leak env? */
}
#endif
}
/*
* Conversation function for authentication thread.
*/
static int
sshpam_thread_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct sshbuf *buffer;
struct pam_ctxt *ctxt;
struct pam_response *reply;
int r, i;
u_char status;
debug3("PAM: %s entering, %d messages", __func__, n);
*resp = NULL;
if (data == NULL) {
error("PAM: conversation function passed a null context");
return (PAM_CONV_ERR);
}
ctxt = data;
if (n <= 0 || n > PAM_MAX_NUM_MSG)
return (PAM_CONV_ERR);
if ((reply = calloc(n, sizeof(*reply))) == NULL)
return PAM_CONV_ERR;
if ((buffer = sshbuf_new()) == NULL) {
free(reply);
return PAM_CONV_ERR;
}
for (i = 0; i < n; ++i) {
switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
case PAM_PROMPT_ECHO_OFF:
case PAM_PROMPT_ECHO_ON:
if ((r = sshbuf_put_cstring(buffer,
PAM_MSG_MEMBER(msg, i, msg))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if (ssh_msg_send(ctxt->pam_csock,
PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1)
goto fail;
if (ssh_msg_recv(ctxt->pam_csock, buffer) == -1)
goto fail;
if ((r = sshbuf_get_u8(buffer, &status)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if (status != PAM_AUTHTOK)
goto fail;
if ((r = sshbuf_get_cstring(buffer,
&reply[i].resp, NULL)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
if ((r = sshbuf_put_cstring(buffer,
PAM_MSG_MEMBER(msg, i, msg))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if (ssh_msg_send(ctxt->pam_csock,
PAM_MSG_MEMBER(msg, i, msg_style), buffer) == -1)
goto fail;
break;
default:
goto fail;
}
sshbuf_reset(buffer);
}
sshbuf_free(buffer);
*resp = reply;
return (PAM_SUCCESS);
fail:
for(i = 0; i < n; i++) {
free(reply[i].resp);
}
free(reply);
sshbuf_free(buffer);
return (PAM_CONV_ERR);
}
/*
* Authentication thread.
*/
static void *
sshpam_thread(void *ctxtp)
{
struct pam_ctxt *ctxt = ctxtp;
struct sshbuf *buffer = NULL;
struct pam_conv sshpam_conv;
int r, flags = (options.permit_empty_passwd == 0 ?
PAM_DISALLOW_NULL_AUTHTOK : 0);
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
extern char **environ;
char **env_from_pam;
u_int i;
const char *pam_user;
const char **ptr_pam_user = &pam_user;
char *tz = getenv("TZ");
sshpam_err = pam_get_item(sshpam_handle, PAM_USER,
(sshpam_const void **)ptr_pam_user);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
environ[0] = NULL;
if (tz != NULL)
if (setenv("TZ", tz, 1) == -1)
error("PAM: could not set TZ environment: %s",
strerror(errno));
if (sshpam_authctxt != NULL) {
setproctitle("%s [pam]",
sshpam_authctxt->valid ? pam_user : "unknown");
}
#endif
sshpam_conv.conv = sshpam_thread_conv;
sshpam_conv.appdata_ptr = ctxt;
if (sshpam_authctxt == NULL)
fatal("%s: PAM authctxt not initialized", __func__);
if ((buffer = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&sshpam_conv);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
sshpam_err = pam_authenticate(sshpam_handle, flags);
if (sshpam_err == PAM_MAXTRIES)
sshpam_set_maxtries_reached(1);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
if (!do_pam_account()) {
sshpam_err = PAM_ACCT_EXPIRED;
goto auth_fail;
}
if (sshpam_authctxt->force_pwchange) {
sshpam_err = pam_chauthtok(sshpam_handle,
PAM_CHANGE_EXPIRED_AUTHTOK);
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
sshpam_password_change_required(0);
}
if ((r = sshbuf_put_cstring(buffer, "OK")) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifndef UNSUPPORTED_POSIX_THREADS_HACK
/* Export variables set by do_pam_account */
if ((r = sshbuf_put_u32(buffer, sshpam_account_status)) != 0 ||
(r = sshbuf_put_u32(buffer, sshpam_authctxt->force_pwchange)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* Export any environment strings set in child */
for (i = 0; environ[i] != NULL; i++) {
/* Count */
if (i > INT_MAX)
fatal("%s: too many enviornment strings", __func__);
}
if ((r = sshbuf_put_u32(buffer, i)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; environ[i] != NULL; i++) {
if ((r = sshbuf_put_cstring(buffer, environ[i])) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Export any environment strings set by PAM in child */
env_from_pam = pam_getenvlist(sshpam_handle);
for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) {
/* Count */
if (i > INT_MAX)
fatal("%s: too many PAM enviornment strings", __func__);
}
if ((r = sshbuf_put_u32(buffer, i)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) {
if ((r = sshbuf_put_cstring(buffer, env_from_pam[i])) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
#endif /* UNSUPPORTED_POSIX_THREADS_HACK */
/* XXX - can't do much about an error here */
ssh_msg_send(ctxt->pam_csock, sshpam_err, buffer);
sshbuf_free(buffer);
pthread_exit(NULL);
auth_fail:
if ((r = sshbuf_put_cstring(buffer,
pam_strerror(sshpam_handle, sshpam_err))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* XXX - can't do much about an error here */
if (sshpam_err == PAM_ACCT_EXPIRED)
ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer);
else if (sshpam_maxtries_reached)
ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer);
else
ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, buffer);
sshbuf_free(buffer);
pthread_exit(NULL);
return (NULL); /* Avoid warning for non-pthread case */
}
void
sshpam_thread_cleanup(void)
{
struct pam_ctxt *ctxt = cleanup_ctxt;
debug3("PAM: %s entering", __func__);
if (ctxt != NULL && ctxt->pam_thread != 0) {
pthread_cancel(ctxt->pam_thread);
pthread_join(ctxt->pam_thread, NULL);
close(ctxt->pam_psock);
close(ctxt->pam_csock);
memset(ctxt, 0, sizeof(*ctxt));
cleanup_ctxt = NULL;
}
}
static int
sshpam_null_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
debug3("PAM: %s entering, %d messages", __func__, n);
return (PAM_CONV_ERR);
}
static struct pam_conv null_conv = { sshpam_null_conv, NULL };
static int
sshpam_store_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct pam_response *reply;
int r, i;
debug3("PAM: %s called with %d messages", __func__, n);
*resp = NULL;
if (n <= 0 || n > PAM_MAX_NUM_MSG)
return (PAM_CONV_ERR);
if ((reply = calloc(n, sizeof(*reply))) == NULL)
return (PAM_CONV_ERR);
for (i = 0; i < n; ++i) {
switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
if ((r = sshbuf_putf(loginmsg, "%s\n",
PAM_MSG_MEMBER(msg, i, msg))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
reply[i].resp_retcode = PAM_SUCCESS;
break;
default:
goto fail;
}
}
*resp = reply;
return (PAM_SUCCESS);
fail:
for(i = 0; i < n; i++) {
free(reply[i].resp);
}
free(reply);
return (PAM_CONV_ERR);
}
static struct pam_conv store_conv = { sshpam_store_conv, NULL };
void
sshpam_cleanup(void)
{
if (sshpam_handle == NULL || (use_privsep && !mm_is_monitor()))
return;
debug("PAM: cleanup");
pam_set_item(sshpam_handle, PAM_CONV, (const void *)&null_conv);
if (sshpam_session_open) {
debug("PAM: closing session");
pam_close_session(sshpam_handle, PAM_SILENT);
sshpam_session_open = 0;
}
if (sshpam_cred_established) {
debug("PAM: deleting credentials");
pam_setcred(sshpam_handle, PAM_DELETE_CRED);
sshpam_cred_established = 0;
}
sshpam_authenticated = 0;
pam_end(sshpam_handle, sshpam_err);
sshpam_handle = NULL;
}
static int
-sshpam_init(Authctxt *authctxt)
+sshpam_init(struct ssh *ssh, Authctxt *authctxt)
{
- const char *pam_rhost, *pam_user, *user = authctxt->user;
+ const char *pam_user, *user = authctxt->user;
const char **ptr_pam_user = &pam_user;
- struct ssh *ssh = active_state; /* XXX */
- if (sshpam_handle != NULL) {
+ if (sshpam_handle == NULL) {
+ if (ssh == NULL) {
+ fatal("%s: called initially with no "
+ "packet context", __func__);
+ }
+ } if (sshpam_handle != NULL) {
/* We already have a PAM context; check if the user matches */
sshpam_err = pam_get_item(sshpam_handle,
PAM_USER, (sshpam_const void **)ptr_pam_user);
if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0)
return (0);
pam_end(sshpam_handle, sshpam_err);
sshpam_handle = NULL;
}
debug("PAM: initializing for \"%s\"", user);
sshpam_err =
pam_start(SSHD_PAM_SERVICE, user, &store_conv, &sshpam_handle);
sshpam_authctxt = authctxt;
if (sshpam_err != PAM_SUCCESS) {
pam_end(sshpam_handle, sshpam_err);
sshpam_handle = NULL;
return (-1);
}
- pam_rhost = auth_get_canonical_hostname(ssh, options.use_dns);
- debug("PAM: setting PAM_RHOST to \"%s\"", pam_rhost);
- sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, pam_rhost);
- if (sshpam_err != PAM_SUCCESS) {
- pam_end(sshpam_handle, sshpam_err);
- sshpam_handle = NULL;
- return (-1);
+
+ if (ssh != NULL && sshpam_rhost == NULL) {
+ /*
+ * We need to cache these as we don't have packet context
+ * during the kbdint flow.
+ */
+ sshpam_rhost = xstrdup(auth_get_canonical_hostname(ssh,
+ options.use_dns));
+ sshpam_laddr = get_local_ipaddr(
+ ssh_packet_get_connection_in(ssh));
+ xasprintf(&sshpam_conninfo, "SSH_CONNECTION=%.50s %d %.50s %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ sshpam_laddr, ssh_local_port(ssh));
}
+ if (sshpam_rhost != NULL) {
+ debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost);
+ sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST,
+ sshpam_rhost);
+ if (sshpam_err != PAM_SUCCESS) {
+ pam_end(sshpam_handle, sshpam_err);
+ sshpam_handle = NULL;
+ return (-1);
+ }
+ /* Put SSH_CONNECTION in the PAM environment too */
+ pam_putenv(sshpam_handle, sshpam_conninfo);
+ }
+
#ifdef PAM_TTY_KLUDGE
/*
* Some silly PAM modules (e.g. pam_time) require a TTY to operate.
* sshd doesn't set the tty until too late in the auth process and
* may not even set one (for tty-less connections)
*/
debug("PAM: setting PAM_TTY to \"ssh\"");
sshpam_err = pam_set_item(sshpam_handle, PAM_TTY, "ssh");
if (sshpam_err != PAM_SUCCESS) {
pam_end(sshpam_handle, sshpam_err);
sshpam_handle = NULL;
return (-1);
}
#endif
return (0);
}
static void
expose_authinfo(const char *caller)
{
char *auth_info;
/*
* Expose authentication information to PAM.
* The environment variable is versioned. Please increment the
* version suffix if the format of session_info changes.
*/
if (sshpam_authctxt->session_info == NULL)
auth_info = xstrdup("");
else if ((auth_info = sshbuf_dup_string(
sshpam_authctxt->session_info)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
debug2("%s: auth information in SSH_AUTH_INFO_0", caller);
do_pam_putenv("SSH_AUTH_INFO_0", auth_info);
free(auth_info);
}
static void *
sshpam_init_ctx(Authctxt *authctxt)
{
struct pam_ctxt *ctxt;
int socks[2];
debug3("PAM: %s entering", __func__);
/*
* Refuse to start if we don't have PAM enabled or do_pam_account
* has previously failed.
*/
if (!options.use_pam || sshpam_account_status == 0)
return NULL;
/* Initialize PAM */
- if (sshpam_init(authctxt) == -1) {
+ if (sshpam_init(NULL, authctxt) == -1) {
error("PAM: initialization failed");
return (NULL);
}
expose_authinfo(__func__);
ctxt = xcalloc(1, sizeof *ctxt);
/* Start the authentication thread */
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) == -1) {
error("PAM: failed create sockets: %s", strerror(errno));
free(ctxt);
return (NULL);
}
ctxt->pam_psock = socks[0];
ctxt->pam_csock = socks[1];
if (pthread_create(&ctxt->pam_thread, NULL, sshpam_thread, ctxt) == -1) {
error("PAM: failed to start authentication thread: %s",
strerror(errno));
close(socks[0]);
close(socks[1]);
free(ctxt);
return (NULL);
}
cleanup_ctxt = ctxt;
return (ctxt);
}
static int
sshpam_query(void *ctx, char **name, char **info,
u_int *num, char ***prompts, u_int **echo_on)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshbuf *buffer;
struct pam_ctxt *ctxt = ctx;
size_t plen;
u_char type;
char *msg;
size_t len, mlen;
int r;
debug3("PAM: %s entering", __func__);
if ((buffer = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
*name = xstrdup("");
*info = xstrdup("");
*prompts = xmalloc(sizeof(char *));
**prompts = NULL;
plen = 0;
*echo_on = xmalloc(sizeof(u_int));
while (ssh_msg_recv(ctxt->pam_psock, buffer) == 0) {
if ((r = sshbuf_get_u8(buffer, &type)) != 0 ||
(r = sshbuf_get_cstring(buffer, &msg, &mlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
switch (type) {
case PAM_PROMPT_ECHO_ON:
case PAM_PROMPT_ECHO_OFF:
*num = 1;
len = plen + mlen + 1;
**prompts = xreallocarray(**prompts, 1, len);
strlcpy(**prompts + plen, msg, len - plen);
plen += mlen;
**echo_on = (type == PAM_PROMPT_ECHO_ON);
free(msg);
return (0);
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
/* accumulate messages */
len = plen + mlen + 2;
**prompts = xreallocarray(**prompts, 1, len);
strlcpy(**prompts + plen, msg, len - plen);
plen += mlen;
strlcat(**prompts + plen, "\n", len - plen);
plen++;
free(msg);
break;
case PAM_ACCT_EXPIRED:
case PAM_MAXTRIES:
if (type == PAM_ACCT_EXPIRED)
sshpam_account_status = 0;
if (type == PAM_MAXTRIES)
sshpam_set_maxtries_reached(1);
/* FALLTHROUGH */
case PAM_AUTH_ERR:
debug3("PAM: %s", pam_strerror(sshpam_handle, type));
if (**prompts != NULL && strlen(**prompts) != 0) {
*info = **prompts;
**prompts = NULL;
*num = 0;
**echo_on = 0;
ctxt->pam_done = -1;
free(msg);
return 0;
}
/* FALLTHROUGH */
case PAM_SUCCESS:
if (**prompts != NULL) {
/* drain any accumulated messages */
debug("PAM: %s", **prompts);
if ((r = sshbuf_put(loginmsg, **prompts,
strlen(**prompts))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
free(**prompts);
**prompts = NULL;
}
if (type == PAM_SUCCESS) {
if (!sshpam_authctxt->valid ||
(sshpam_authctxt->pw->pw_uid == 0 &&
options.permit_root_login != PERMIT_YES))
fatal("Internal error: PAM auth "
"succeeded when it should have "
"failed");
import_environments(buffer);
*num = 0;
**echo_on = 0;
ctxt->pam_done = 1;
free(msg);
return (0);
}
error("PAM: %s for %s%.100s from %.100s", msg,
sshpam_authctxt->valid ? "" : "illegal user ",
- sshpam_authctxt->user,
- auth_get_canonical_hostname(ssh, options.use_dns));
+ sshpam_authctxt->user, sshpam_rhost);
/* FALLTHROUGH */
default:
*num = 0;
**echo_on = 0;
free(msg);
ctxt->pam_done = -1;
return (-1);
}
}
return (-1);
}
/*
* Returns a junk password of identical length to that the user supplied.
* Used to mitigate timing attacks against crypt(3)/PAM stacks that
* vary processing time in proportion to password length.
*/
static char *
fake_password(const char *wire_password)
{
const char junk[] = "\b\n\r\177INCORRECT";
char *ret = NULL;
size_t i, l = wire_password != NULL ? strlen(wire_password) : 0;
if (l >= INT_MAX)
fatal("%s: password length too long: %zu", __func__, l);
ret = malloc(l + 1);
if (ret == NULL)
return NULL;
for (i = 0; i < l; i++)
ret[i] = junk[i % (sizeof(junk) - 1)];
ret[i] = '\0';
return ret;
}
/* XXX - see also comment in auth-chall.c:verify_response */
static int
sshpam_respond(void *ctx, u_int num, char **resp)
{
struct sshbuf *buffer;
struct pam_ctxt *ctxt = ctx;
char *fake;
int r;
debug2("PAM: %s entering, %u responses", __func__, num);
switch (ctxt->pam_done) {
case 1:
sshpam_authenticated = 1;
return (0);
case 0:
break;
default:
return (-1);
}
if (num != 1) {
error("PAM: expected one response, got %u", num);
return (-1);
}
if ((buffer = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (sshpam_authctxt->valid &&
(sshpam_authctxt->pw->pw_uid != 0 ||
options.permit_root_login == PERMIT_YES)) {
if ((r = sshbuf_put_cstring(buffer, *resp)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else {
fake = fake_password(*resp);
if ((r = sshbuf_put_cstring(buffer, fake)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(fake);
}
if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, buffer) == -1) {
sshbuf_free(buffer);
return (-1);
}
sshbuf_free(buffer);
return (1);
}
static void
sshpam_free_ctx(void *ctxtp)
{
struct pam_ctxt *ctxt = ctxtp;
debug3("PAM: %s entering", __func__);
sshpam_thread_cleanup();
free(ctxt);
/*
* We don't call sshpam_cleanup() here because we may need the PAM
* handle at a later stage, e.g. when setting up a session. It's
* still on the cleanup list, so pam_end() *will* be called before
* the server process terminates.
*/
}
KbdintDevice sshpam_device = {
"pam",
sshpam_init_ctx,
sshpam_query,
sshpam_respond,
sshpam_free_ctx
};
KbdintDevice mm_sshpam_device = {
"pam",
mm_sshpam_init_ctx,
mm_sshpam_query,
mm_sshpam_respond,
mm_sshpam_free_ctx
};
/*
* This replaces auth-pam.c
*/
void
-start_pam(Authctxt *authctxt)
+start_pam(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+
if (!options.use_pam)
fatal("PAM: initialisation requested when UsePAM=no");
- if (sshpam_init(authctxt) == -1)
+ if (sshpam_init(ssh, authctxt) == -1)
fatal("PAM: initialisation failed");
}
void
finish_pam(void)
{
sshpam_cleanup();
}
u_int
do_pam_account(void)
{
debug("%s: called", __func__);
if (sshpam_account_status != -1)
return (sshpam_account_status);
expose_authinfo(__func__);
sshpam_err = pam_acct_mgmt(sshpam_handle, 0);
debug3("PAM: %s pam_acct_mgmt = %d (%s)", __func__, sshpam_err,
pam_strerror(sshpam_handle, sshpam_err));
if (sshpam_err != PAM_SUCCESS && sshpam_err != PAM_NEW_AUTHTOK_REQD) {
sshpam_account_status = 0;
return (sshpam_account_status);
}
if (sshpam_err == PAM_NEW_AUTHTOK_REQD)
sshpam_password_change_required(1);
sshpam_account_status = 1;
return (sshpam_account_status);
}
void
do_pam_setcred(int init)
{
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&store_conv);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: failed to set PAM_CONV: %s",
pam_strerror(sshpam_handle, sshpam_err));
if (init) {
debug("PAM: establishing credentials");
sshpam_err = pam_setcred(sshpam_handle, PAM_ESTABLISH_CRED);
} else {
debug("PAM: reinitializing credentials");
sshpam_err = pam_setcred(sshpam_handle, PAM_REINITIALIZE_CRED);
}
if (sshpam_err == PAM_SUCCESS) {
sshpam_cred_established = 1;
return;
}
if (sshpam_authenticated)
fatal("PAM: pam_setcred(): %s",
pam_strerror(sshpam_handle, sshpam_err));
else
debug("PAM: pam_setcred(): %s",
pam_strerror(sshpam_handle, sshpam_err));
}
static int
sshpam_tty_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
char input[PAM_MAX_MSG_SIZE];
struct pam_response *reply;
int i;
debug3("PAM: %s called with %d messages", __func__, n);
*resp = NULL;
if (n <= 0 || n > PAM_MAX_NUM_MSG || !isatty(STDIN_FILENO))
return (PAM_CONV_ERR);
if ((reply = calloc(n, sizeof(*reply))) == NULL)
return (PAM_CONV_ERR);
for (i = 0; i < n; ++i) {
switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
case PAM_PROMPT_ECHO_OFF:
reply[i].resp =
read_passphrase(PAM_MSG_MEMBER(msg, i, msg),
RP_ALLOW_STDIN);
reply[i].resp_retcode = PAM_SUCCESS;
break;
case PAM_PROMPT_ECHO_ON:
fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
if (fgets(input, sizeof input, stdin) == NULL)
input[0] = '\0';
if ((reply[i].resp = strdup(input)) == NULL)
goto fail;
reply[i].resp_retcode = PAM_SUCCESS;
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
fprintf(stderr, "%s\n", PAM_MSG_MEMBER(msg, i, msg));
reply[i].resp_retcode = PAM_SUCCESS;
break;
default:
goto fail;
}
}
*resp = reply;
return (PAM_SUCCESS);
fail:
for(i = 0; i < n; i++) {
free(reply[i].resp);
}
free(reply);
return (PAM_CONV_ERR);
}
static struct pam_conv tty_conv = { sshpam_tty_conv, NULL };
/*
* XXX this should be done in the authentication phase, but ssh1 doesn't
* support that
*/
void
do_pam_chauthtok(void)
{
if (use_privsep)
fatal("Password expired (unable to change with privsep)");
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&tty_conv);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: failed to set PAM_CONV: %s",
pam_strerror(sshpam_handle, sshpam_err));
debug("PAM: changing password");
sshpam_err = pam_chauthtok(sshpam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: pam_chauthtok(): %s",
pam_strerror(sshpam_handle, sshpam_err));
}
void
do_pam_session(struct ssh *ssh)
{
debug3("PAM: opening session");
expose_authinfo(__func__);
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&store_conv);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: failed to set PAM_CONV: %s",
pam_strerror(sshpam_handle, sshpam_err));
sshpam_err = pam_open_session(sshpam_handle, 0);
if (sshpam_err == PAM_SUCCESS)
sshpam_session_open = 1;
else {
sshpam_session_open = 0;
auth_restrict_session(ssh);
error("PAM: pam_open_session(): %s",
pam_strerror(sshpam_handle, sshpam_err));
}
}
int
is_pam_session_open(void)
{
return sshpam_session_open;
}
/*
* Set a PAM environment string. We need to do this so that the session
* modules can handle things like Kerberos/GSI credentials that appear
* during the ssh authentication process.
*/
int
do_pam_putenv(char *name, char *value)
{
int ret = 1;
#ifdef HAVE_PAM_PUTENV
char *compound;
size_t len;
len = strlen(name) + strlen(value) + 2;
compound = xmalloc(len);
snprintf(compound, len, "%s=%s", name, value);
ret = pam_putenv(sshpam_handle, compound);
free(compound);
#endif
return (ret);
}
char **
fetch_pam_child_environment(void)
{
return sshpam_env;
}
char **
fetch_pam_environment(void)
{
return (pam_getenvlist(sshpam_handle));
}
void
free_pam_environment(char **env)
{
char **envp;
if (env == NULL)
return;
for (envp = env; *envp; envp++)
free(*envp);
free(env);
}
/*
* "Blind" conversation function for password authentication. Assumes that
* echo-off prompts are for the password and stores messages for later
* display.
*/
static int
sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg,
struct pam_response **resp, void *data)
{
struct pam_response *reply;
int r, i;
size_t len;
debug3("PAM: %s called with %d messages", __func__, n);
*resp = NULL;
if (n <= 0 || n > PAM_MAX_NUM_MSG)
return (PAM_CONV_ERR);
if ((reply = calloc(n, sizeof(*reply))) == NULL)
return (PAM_CONV_ERR);
for (i = 0; i < n; ++i) {
switch (PAM_MSG_MEMBER(msg, i, msg_style)) {
case PAM_PROMPT_ECHO_OFF:
if (sshpam_password == NULL)
goto fail;
if ((reply[i].resp = strdup(sshpam_password)) == NULL)
goto fail;
reply[i].resp_retcode = PAM_SUCCESS;
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
len = strlen(PAM_MSG_MEMBER(msg, i, msg));
if (len > 0) {
if ((r = sshbuf_putf(loginmsg, "%s\n",
PAM_MSG_MEMBER(msg, i, msg))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
if ((reply[i].resp = strdup("")) == NULL)
goto fail;
reply[i].resp_retcode = PAM_SUCCESS;
break;
default:
goto fail;
}
}
*resp = reply;
return (PAM_SUCCESS);
fail:
for(i = 0; i < n; i++) {
free(reply[i].resp);
}
free(reply);
return (PAM_CONV_ERR);
}
static struct pam_conv passwd_conv = { sshpam_passwd_conv, NULL };
/*
* Attempt password authentication via PAM
*/
int
sshpam_auth_passwd(Authctxt *authctxt, const char *password)
{
int flags = (options.permit_empty_passwd == 0 ?
PAM_DISALLOW_NULL_AUTHTOK : 0);
char *fake = NULL;
if (!options.use_pam || sshpam_handle == NULL)
fatal("PAM: %s called when PAM disabled or failed to "
"initialise.", __func__);
sshpam_password = password;
sshpam_authctxt = authctxt;
/*
* If the user logging in is invalid, or is root but is not permitted
* by PermitRootLogin, use an invalid password to prevent leaking
* information via timing (eg if the PAM config has a delay on fail).
*/
if (!authctxt->valid || (authctxt->pw->pw_uid == 0 &&
options.permit_root_login != PERMIT_YES))
sshpam_password = fake = fake_password(password);
sshpam_err = pam_set_item(sshpam_handle, PAM_CONV,
(const void *)&passwd_conv);
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: %s: failed to set PAM_CONV: %s", __func__,
pam_strerror(sshpam_handle, sshpam_err));
sshpam_err = pam_authenticate(sshpam_handle, flags);
sshpam_password = NULL;
free(fake);
if (sshpam_err == PAM_MAXTRIES)
sshpam_set_maxtries_reached(1);
if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
debug("PAM: password authentication accepted for %.100s",
authctxt->user);
return 1;
} else {
debug("PAM: password authentication failed for %.100s: %s",
authctxt->valid ? authctxt->user : "an illegal user",
pam_strerror(sshpam_handle, sshpam_err));
return 0;
}
}
int
sshpam_get_maxtries_reached(void)
{
return sshpam_maxtries_reached;
}
void
sshpam_set_maxtries_reached(int reached)
{
if (reached == 0 || sshpam_maxtries_reached)
return;
sshpam_maxtries_reached = 1;
options.password_authentication = 0;
options.kbd_interactive_authentication = 0;
options.challenge_response_authentication = 0;
}
#endif /* USE_PAM */
diff --git a/auth-pam.h b/auth-pam.h
index 4198607454fb..9fcea270faec 100644
--- a/auth-pam.h
+++ b/auth-pam.h
@@ -1,47 +1,47 @@
/*
* Copyright (c) 2000 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef USE_PAM
struct ssh;
-void start_pam(Authctxt *);
+void start_pam(struct ssh *);
void finish_pam(void);
u_int do_pam_account(void);
void do_pam_session(struct ssh *);
void do_pam_setcred(int );
void do_pam_chauthtok(void);
int do_pam_putenv(char *, char *);
char ** fetch_pam_environment(void);
char ** fetch_pam_child_environment(void);
void free_pam_environment(char **);
void sshpam_thread_cleanup(void);
void sshpam_cleanup(void);
int sshpam_auth_passwd(Authctxt *, const char *);
int sshpam_get_maxtries_reached(void);
void sshpam_set_maxtries_reached(int);
int is_pam_session_open(void);
#endif /* USE_PAM */
diff --git a/auth.c b/auth.c
index 3ca3762cc612..8696f258e883 100644
--- a/auth.c
+++ b/auth.c
@@ -1,1202 +1,1188 @@
-/* $OpenBSD: auth.c,v 1.133 2018/09/12 01:19:12 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.138 2019/01/19 21:41:18 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <pwd.h>
#ifdef HAVE_LOGIN_H
#include <login.h>
#endif
#ifdef USE_SHADOW
#include <shadow.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <netdb.h>
+#include <time.h>
#include "xmalloc.h"
#include "match.h"
#include "groupaccess.h"
#include "log.h"
#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "canohost.h"
#include "uidswap.h"
#include "packet.h"
#include "loginrec.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "authfile.h"
#include "monitor_wrap.h"
#include "authfile.h"
#include "ssherr.h"
#include "compat.h"
#include "channels.h"
/* import */
extern ServerOptions options;
extern int use_privsep;
extern struct sshbuf *loginmsg;
extern struct passwd *privsep_pw;
extern struct sshauthopt *auth_opts;
/* Debugging messages */
static struct sshbuf *auth_debug;
/*
* Check if the user is allowed to log in via ssh. If user is listed
* in DenyUsers or one of user's groups is listed in DenyGroups, false
* will be returned. If AllowUsers isn't empty and user isn't listed
* there, or if AllowGroups isn't empty and one of user's groups isn't
* listed there, false will be returned.
* If the user's shell is not executable, false will be returned.
* Otherwise true is returned.
*/
int
-allowed_user(struct passwd * pw)
+allowed_user(struct ssh *ssh, struct passwd * pw)
{
- struct ssh *ssh = active_state; /* XXX */
struct stat st;
const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
u_int i;
int r;
#ifdef USE_SHADOW
struct spwd *spw = NULL;
#endif
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
if (!pw || !pw->pw_name)
return 0;
#ifdef USE_SHADOW
if (!options.use_pam)
spw = getspnam(pw->pw_name);
#ifdef HAS_SHADOW_EXPIRE
if (!options.use_pam && spw != NULL && auth_shadow_acctexpired(spw))
return 0;
#endif /* HAS_SHADOW_EXPIRE */
#endif /* USE_SHADOW */
/* grab passwd field for locked account check */
passwd = pw->pw_passwd;
#ifdef USE_SHADOW
if (spw != NULL)
#ifdef USE_LIBIAF
passwd = get_iaf_password(pw);
#else
passwd = spw->sp_pwdp;
#endif /* USE_LIBIAF */
#endif
/* check for locked account */
if (!options.use_pam && passwd && *passwd) {
int locked = 0;
#ifdef LOCKED_PASSWD_STRING
if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0)
locked = 1;
#endif
#ifdef LOCKED_PASSWD_PREFIX
if (strncmp(passwd, LOCKED_PASSWD_PREFIX,
strlen(LOCKED_PASSWD_PREFIX)) == 0)
locked = 1;
#endif
#ifdef LOCKED_PASSWD_SUBSTR
if (strstr(passwd, LOCKED_PASSWD_SUBSTR))
locked = 1;
#endif
#ifdef USE_LIBIAF
free((void *) passwd);
#endif /* USE_LIBIAF */
if (locked) {
logit("User %.100s not allowed because account is locked",
pw->pw_name);
return 0;
}
}
/*
* Deny if shell does not exist or is not executable unless we
* are chrooting.
*/
if (options.chroot_directory == NULL ||
strcasecmp(options.chroot_directory, "none") == 0) {
char *shell = xstrdup((pw->pw_shell[0] == '\0') ?
_PATH_BSHELL : pw->pw_shell); /* empty = /bin/sh */
if (stat(shell, &st) != 0) {
logit("User %.100s not allowed because shell %.100s "
"does not exist", pw->pw_name, shell);
free(shell);
return 0;
}
if (S_ISREG(st.st_mode) == 0 ||
(st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP)) == 0) {
logit("User %.100s not allowed because shell %.100s "
"is not executable", pw->pw_name, shell);
free(shell);
return 0;
}
free(shell);
}
if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
options.num_deny_groups > 0 || options.num_allow_groups > 0) {
hostname = auth_get_canonical_hostname(ssh, options.use_dns);
ipaddr = ssh_remote_ipaddr(ssh);
}
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
for (i = 0; i < options.num_deny_users; i++) {
r = match_user(pw->pw_name, hostname, ipaddr,
options.deny_users[i]);
if (r < 0) {
fatal("Invalid DenyUsers pattern \"%.100s\"",
options.deny_users[i]);
} else if (r != 0) {
logit("User %.100s from %.100s not allowed "
"because listed in DenyUsers",
pw->pw_name, hostname);
return 0;
}
}
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
for (i = 0; i < options.num_allow_users; i++) {
r = match_user(pw->pw_name, hostname, ipaddr,
options.allow_users[i]);
if (r < 0) {
fatal("Invalid AllowUsers pattern \"%.100s\"",
options.allow_users[i]);
} else if (r == 1)
break;
}
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users) {
logit("User %.100s from %.100s not allowed because "
"not listed in AllowUsers", pw->pw_name, hostname);
return 0;
}
}
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
/* Get the user's group access list (primary and supplementary) */
if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
logit("User %.100s from %.100s not allowed because "
"not in any group", pw->pw_name, hostname);
return 0;
}
/* Return false if one of user's groups is listed in DenyGroups */
if (options.num_deny_groups > 0)
if (ga_match(options.deny_groups,
options.num_deny_groups)) {
ga_free();
logit("User %.100s from %.100s not allowed "
"because a group is listed in DenyGroups",
pw->pw_name, hostname);
return 0;
}
/*
* Return false if AllowGroups isn't empty and one of user's groups
* isn't listed there
*/
if (options.num_allow_groups > 0)
if (!ga_match(options.allow_groups,
options.num_allow_groups)) {
ga_free();
logit("User %.100s from %.100s not allowed "
"because none of user's groups are listed "
"in AllowGroups", pw->pw_name, hostname);
return 0;
}
ga_free();
}
#ifdef CUSTOM_SYS_AUTH_ALLOWED_USER
- if (!sys_auth_allowed_user(pw, &loginmsg))
+ if (!sys_auth_allowed_user(pw, loginmsg))
return 0;
#endif
/* We found no reason not to let this user try to log on... */
return 1;
}
/*
* Formats any key left in authctxt->auth_method_key for inclusion in
* auth_log()'s message. Also includes authxtct->auth_method_info if present.
*/
static char *
format_method_key(Authctxt *authctxt)
{
const struct sshkey *key = authctxt->auth_method_key;
const char *methinfo = authctxt->auth_method_info;
char *fp, *cafp, *ret = NULL;
if (key == NULL)
return NULL;
if (sshkey_is_cert(key)) {
fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT);
cafp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
xasprintf(&ret, "%s %s ID %s (serial %llu) CA %s %s%s%s",
sshkey_type(key), fp == NULL ? "(null)" : fp,
key->cert->key_id,
(unsigned long long)key->cert->serial,
sshkey_type(key->cert->signature_key),
cafp == NULL ? "(null)" : cafp,
methinfo == NULL ? "" : ", ",
methinfo == NULL ? "" : methinfo);
free(fp);
free(cafp);
} else {
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
xasprintf(&ret, "%s %s%s%s", sshkey_type(key),
fp == NULL ? "(null)" : fp,
methinfo == NULL ? "" : ", ",
methinfo == NULL ? "" : methinfo);
free(fp);
}
return ret;
}
void
-auth_log(Authctxt *authctxt, int authenticated, int partial,
+auth_log(struct ssh *ssh, int authenticated, int partial,
const char *method, const char *submethod)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
int level = SYSLOG_LEVEL_VERBOSE;
const char *authmsg;
char *extra = NULL;
if (use_privsep && !mm_is_monitor() && !authctxt->postponed)
return;
/* Raise logging level */
if (authenticated == 1 ||
!authctxt->valid ||
authctxt->failures >= options.max_authtries / 2 ||
strcmp(method, "password") == 0)
level = SYSLOG_LEVEL_INFO;
if (authctxt->postponed)
authmsg = "Postponed";
else if (partial)
authmsg = "Partial";
else
authmsg = authenticated ? "Accepted" : "Failed";
if ((extra = format_method_key(authctxt)) == NULL) {
if (authctxt->auth_method_info != NULL)
extra = xstrdup(authctxt->auth_method_info);
}
do_log2(level, "%s %s%s%s for %s%.100s from %.200s port %d ssh2%s%s",
authmsg,
method,
submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
authctxt->valid ? "" : "invalid user ",
authctxt->user,
ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh),
extra != NULL ? ": " : "",
extra != NULL ? extra : "");
free(extra);
#ifdef CUSTOM_FAILED_LOGIN
if (authenticated == 0 && !authctxt->postponed &&
(strcmp(method, "password") == 0 ||
strncmp(method, "keyboard-interactive", 20) == 0 ||
strcmp(method, "challenge-response") == 0))
- record_failed_login(authctxt->user,
+ record_failed_login(ssh, authctxt->user,
auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
# ifdef WITH_AIXAUTHENTICATE
if (authenticated)
sys_auth_record_login(authctxt->user,
auth_get_canonical_hostname(ssh, options.use_dns), "ssh",
- &loginmsg);
+ loginmsg);
# endif
#endif
#ifdef SSH_AUDIT_EVENTS
if (authenticated == 0 && !authctxt->postponed)
- audit_event(audit_classify_auth(method));
+ audit_event(ssh, audit_classify_auth(method));
#endif
}
void
-auth_maxtries_exceeded(Authctxt *authctxt)
+auth_maxtries_exceeded(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
error("maximum authentication attempts exceeded for "
"%s%.100s from %.200s port %d ssh2",
authctxt->valid ? "" : "invalid user ",
authctxt->user,
ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh));
- packet_disconnect("Too many authentication failures");
+ ssh_packet_disconnect(ssh, "Too many authentication failures");
/* NOTREACHED */
}
/*
* Check whether root logins are disallowed.
*/
int
auth_root_allowed(struct ssh *ssh, const char *method)
{
switch (options.permit_root_login) {
case PERMIT_YES:
return 1;
case PERMIT_NO_PASSWD:
if (strcmp(method, "publickey") == 0 ||
strcmp(method, "hostbased") == 0 ||
strcmp(method, "gssapi-with-mic") == 0)
return 1;
break;
case PERMIT_FORCED_ONLY:
if (auth_opts->force_command != NULL) {
logit("Root login accepted for forced command.");
return 1;
}
break;
}
logit("ROOT LOGIN REFUSED FROM %.200s port %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
return 0;
}
/*
* Given a template and a passwd structure, build a filename
* by substituting % tokenised options. Currently, %% becomes '%',
* %h becomes the home directory and %u the username.
*
* This returns a buffer allocated by xmalloc.
*/
char *
expand_authorized_keys(const char *filename, struct passwd *pw)
{
char *file, uidstr[32], ret[PATH_MAX];
int i;
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
file = percent_expand(filename, "h", pw->pw_dir,
"u", pw->pw_name, "U", uidstr, (char *)NULL);
/*
* Ensure that filename starts anchored. If not, be backward
* compatible and prepend the '%h/'
*/
- if (*file == '/')
+ if (path_absolute(file))
return (file);
i = snprintf(ret, sizeof(ret), "%s/%s", pw->pw_dir, file);
if (i < 0 || (size_t)i >= sizeof(ret))
fatal("expand_authorized_keys: path too long");
free(file);
return (xstrdup(ret));
}
char *
authorized_principals_file(struct passwd *pw)
{
if (options.authorized_principals_file == NULL)
return NULL;
return expand_authorized_keys(options.authorized_principals_file, pw);
}
/* return ok if key exists in sysfile or userfile */
HostStatus
check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
const char *sysfile, const char *userfile)
{
char *user_hostfile;
struct stat st;
HostStatus host_status;
struct hostkeys *hostkeys;
const struct hostkey_entry *found;
hostkeys = init_hostkeys();
load_hostkeys(hostkeys, host, sysfile);
if (userfile != NULL) {
user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {
logit("Authentication refused for %.100s: "
"bad owner or modes for %.200s",
pw->pw_name, user_hostfile);
auth_debug_add("Ignored %.200s: bad ownership or modes",
user_hostfile);
} else {
temporarily_use_uid(pw);
load_hostkeys(hostkeys, host, user_hostfile);
restore_uid();
}
free(user_hostfile);
}
host_status = check_key_in_hostkeys(hostkeys, key, &found);
if (host_status == HOST_REVOKED)
error("WARNING: revoked key for %s attempted authentication",
found->host);
else if (host_status == HOST_OK)
debug("%s: key for %s found at %s:%ld", __func__,
found->host, found->file, found->line);
else
debug("%s: key for host %s not found", __func__, host);
free_hostkeys(hostkeys);
return host_status;
}
static FILE *
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
int log_missing, char *file_type)
{
char line[1024];
struct stat st;
int fd;
FILE *f;
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
if (log_missing || errno != ENOENT)
debug("Could not open %s '%s': %s", file_type, file,
strerror(errno));
return NULL;
}
if (fstat(fd, &st) < 0) {
close(fd);
return NULL;
}
if (!S_ISREG(st.st_mode)) {
logit("User %s %s %s is not a regular file",
pw->pw_name, file_type, file);
close(fd);
return NULL;
}
unset_nonblock(fd);
if ((f = fdopen(fd, "r")) == NULL) {
close(fd);
return NULL;
}
if (strict_modes &&
safe_path_fd(fileno(f), file, pw, line, sizeof(line)) != 0) {
fclose(f);
logit("Authentication refused: %s", line);
auth_debug_add("Ignored %s: %s", file_type, line);
return NULL;
}
return f;
}
FILE *
auth_openkeyfile(const char *file, struct passwd *pw, int strict_modes)
{
return auth_openfile(file, pw, strict_modes, 1, "authorized keys");
}
FILE *
auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
{
return auth_openfile(file, pw, strict_modes, 0,
"authorized principals");
}
struct passwd *
-getpwnamallow(const char *user)
+getpwnamallow(struct ssh *ssh, const char *user)
{
- struct ssh *ssh = active_state; /* XXX */
#ifdef HAVE_LOGIN_CAP
extern login_cap_t *lc;
#ifdef BSD_AUTH
auth_session_t *as;
#endif
#endif
struct passwd *pw;
- struct connection_info *ci = get_connection_info(1, options.use_dns);
+ struct connection_info *ci;
+ ci = get_connection_info(ssh, 1, options.use_dns);
ci->user = user;
parse_server_match_config(&options, ci);
log_change_level(options.log_level);
process_permitopen(ssh, &options);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user);
#endif
pw = getpwnam(user);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_restoreauthdb();
-#endif
-#ifdef HAVE_CYGWIN
- /*
- * Windows usernames are case-insensitive. To avoid later problems
- * when trying to match the username, the user is only allowed to
- * login if the username is given in the same case as stored in the
- * user database.
- */
- if (pw != NULL && strcmp(user, pw->pw_name) != 0) {
- logit("Login name %.100s does not match stored username %.100s",
- user, pw->pw_name);
- pw = NULL;
- }
#endif
if (pw == NULL) {
logit("Invalid user %.100s from %.100s port %d",
user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
#ifdef CUSTOM_FAILED_LOGIN
- record_failed_login(user,
+ record_failed_login(ssh, user,
auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
#endif
#ifdef SSH_AUDIT_EVENTS
- audit_event(SSH_INVALID_USER);
+ audit_event(ssh, SSH_INVALID_USER);
#endif /* SSH_AUDIT_EVENTS */
return (NULL);
}
- if (!allowed_user(pw))
+ if (!allowed_user(ssh, pw))
return (NULL);
#ifdef HAVE_LOGIN_CAP
if ((lc = login_getclass(pw->pw_class)) == NULL) {
debug("unable to get login class: %s", user);
return (NULL);
}
#ifdef BSD_AUTH
if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
debug("Approval failure for %s", user);
pw = NULL;
}
if (as != NULL)
auth_close(as);
#endif
#endif
if (pw != NULL)
return (pwcopy(pw));
return (NULL);
}
/* Returns 1 if key is revoked by revoked_keys_file, 0 otherwise */
int
auth_key_is_revoked(struct sshkey *key)
{
char *fp = NULL;
int r;
if (options.revoked_keys_file == NULL)
return 0;
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
error("%s: fingerprint key: %s", __func__, ssh_err(r));
goto out;
}
r = sshkey_check_revoked(key, options.revoked_keys_file);
switch (r) {
case 0:
break; /* not revoked */
case SSH_ERR_KEY_REVOKED:
error("Authentication key %s %s revoked by file %s",
sshkey_type(key), fp, options.revoked_keys_file);
goto out;
default:
error("Error checking authentication key %s %s in "
"revoked keys file %s: %s", sshkey_type(key), fp,
options.revoked_keys_file, ssh_err(r));
goto out;
}
/* Success */
r = 0;
out:
free(fp);
return r == 0 ? 0 : 1;
}
void
auth_debug_add(const char *fmt,...)
{
char buf[1024];
va_list args;
int r;
if (auth_debug == NULL)
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0)
fatal("%s: sshbuf_put_cstring: %s", __func__, ssh_err(r));
}
void
-auth_debug_send(void)
+auth_debug_send(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
char *msg;
int r;
if (auth_debug == NULL)
return;
while (sshbuf_len(auth_debug) != 0) {
if ((r = sshbuf_get_cstring(auth_debug, &msg, NULL)) != 0)
fatal("%s: sshbuf_get_cstring: %s",
__func__, ssh_err(r));
ssh_packet_send_debug(ssh, "%s", msg);
free(msg);
}
}
void
auth_debug_reset(void)
{
if (auth_debug != NULL)
sshbuf_reset(auth_debug);
else if ((auth_debug = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
}
struct passwd *
fakepw(void)
{
static struct passwd fake;
memset(&fake, 0, sizeof(fake));
fake.pw_name = "NOUSER";
fake.pw_passwd =
"$2a$06$r3.juUaHZDlIbQaO2dS9FuYxL1W9M81R1Tc92PoSNmzvpEqLkLGrK";
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
fake.pw_gecos = "NOUSER";
#endif
fake.pw_uid = privsep_pw == NULL ? (uid_t)-1 : privsep_pw->pw_uid;
fake.pw_gid = privsep_pw == NULL ? (gid_t)-1 : privsep_pw->pw_gid;
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
fake.pw_class = "";
#endif
fake.pw_dir = "/nonexist";
fake.pw_shell = "/nonexist";
return (&fake);
}
/*
* Returns the remote DNS hostname as a string. The returned string must not
* be freed. NB. this will usually trigger a DNS query the first time it is
* called.
* This function does additional checks on the hostname to mitigate some
* attacks on legacy rhosts-style authentication.
* XXX is RhostsRSAAuthentication vulnerable to these?
* XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
*/
static char *
remote_hostname(struct ssh *ssh)
{
struct sockaddr_storage from;
socklen_t fromlen;
struct addrinfo hints, *ai, *aitop;
char name[NI_MAXHOST], ntop2[NI_MAXHOST];
const char *ntop = ssh_remote_ipaddr(ssh);
/* Get IP address of client. */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
return strdup(ntop);
}
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
debug3("Trying to reverse map address %.100s.", ntop);
/* Map the IP address to a host name. */
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
NULL, 0, NI_NAMEREQD) != 0) {
/* Host name not found. Use ip address. */
return strdup(ntop);
}
/*
* if reverse lookup result looks like a numeric hostname,
* someone is trying to trick us by PTR record like following:
* 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5
*/
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
name, ntop);
freeaddrinfo(ai);
return strdup(ntop);
}
/* Names are stored in lowercase. */
lowercase(name);
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = from.ss_family;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
logit("reverse mapping checking getaddrinfo for %.700s "
"[%s] failed.", name, ntop);
return strdup(ntop);
}
/* Look for the address from the list of addresses. */
for (ai = aitop; ai; ai = ai->ai_next) {
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
(strcmp(ntop, ntop2) == 0))
break;
}
freeaddrinfo(aitop);
/* If we reached the end of the list, the address was not there. */
if (ai == NULL) {
/* Address not found for the host name. */
logit("Address %.100s maps to %.600s, but this does not "
"map back to the address.", ntop, name);
return strdup(ntop);
}
return strdup(name);
}
/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
* several times.
*/
const char *
auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
{
static char *dnsname;
if (!use_dns)
return ssh_remote_ipaddr(ssh);
else if (dnsname != NULL)
return dnsname;
else {
dnsname = remote_hostname(ssh);
return dnsname;
}
}
/*
* Runs command in a subprocess with a minimal environment.
* Returns pid on success, 0 on failure.
* The child stdout and stderr maybe captured, left attached or sent to
* /dev/null depending on the contents of flags.
* "tag" is prepended to log messages.
* NB. "command" is only used for logging; the actual command executed is
* av[0].
*/
pid_t
subprocess(const char *tag, struct passwd *pw, const char *command,
int ac, char **av, FILE **child, u_int flags)
{
FILE *f = NULL;
struct stat st;
int fd, devnull, p[2], i;
pid_t pid;
char *cp, errmsg[512];
u_int envsize;
char **child_env;
if (child != NULL)
*child = NULL;
debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__,
tag, command, pw->pw_name, flags);
/* Check consistency */
if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
(flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) {
error("%s: inconsistent flags", __func__);
return 0;
}
if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) {
error("%s: inconsistent flags/output", __func__);
return 0;
}
/*
* If executing an explicit binary, then verify the it exists
* and appears safe-ish to execute
*/
- if (*av[0] != '/') {
+ if (!path_absolute(av[0])) {
error("%s path is not absolute", tag);
return 0;
}
temporarily_use_uid(pw);
if (stat(av[0], &st) < 0) {
error("Could not stat %s \"%s\": %s", tag,
av[0], strerror(errno));
restore_uid();
return 0;
}
if (safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
restore_uid();
return 0;
}
/* Prepare to keep the child's stdout if requested */
if (pipe(p) != 0) {
error("%s: pipe: %s", tag, strerror(errno));
restore_uid();
return 0;
}
restore_uid();
switch ((pid = fork())) {
case -1: /* error */
error("%s: fork: %s", tag, strerror(errno));
close(p[0]);
close(p[1]);
return 0;
case 0: /* child */
/* Prepare a minimal environment for the child. */
envsize = 5;
child_env = xcalloc(sizeof(*child_env), envsize);
child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
child_set_env(&child_env, &envsize, "USER", pw->pw_name);
child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
if ((cp = getenv("LANG")) != NULL)
child_set_env(&child_env, &envsize, "LANG", cp);
for (i = 0; i < NSIG; i++)
signal(i, SIG_DFL);
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
error("%s: open %s: %s", tag, _PATH_DEVNULL,
strerror(errno));
_exit(1);
}
if (dup2(devnull, STDIN_FILENO) == -1) {
error("%s: dup2: %s", tag, strerror(errno));
_exit(1);
}
/* Set up stdout as requested; leave stderr in place for now. */
fd = -1;
if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0)
fd = p[1];
else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0)
fd = devnull;
if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) {
error("%s: dup2: %s", tag, strerror(errno));
_exit(1);
}
closefrom(STDERR_FILENO + 1);
/* Don't use permanently_set_uid() here to avoid fatal() */
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
strerror(errno));
_exit(1);
}
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
strerror(errno));
_exit(1);
}
/* stdin is pointed to /dev/null at this point */
if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
error("%s: dup2: %s", tag, strerror(errno));
_exit(1);
}
execve(av[0], av, child_env);
error("%s exec \"%s\": %s", tag, command, strerror(errno));
_exit(127);
default: /* parent */
break;
}
close(p[1]);
if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0)
close(p[0]);
else if ((f = fdopen(p[0], "r")) == NULL) {
error("%s: fdopen: %s", tag, strerror(errno));
close(p[0]);
/* Don't leave zombie child */
kill(pid, SIGTERM);
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
;
return 0;
}
/* Success */
debug3("%s: %s pid %ld", __func__, tag, (long)pid);
if (child != NULL)
*child = f;
return pid;
}
/* These functions link key/cert options to the auth framework */
/* Log sshauthopt options locally and (optionally) for remote transmission */
void
auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
{
int do_env = options.permit_user_env && opts->nenv > 0;
int do_permitopen = opts->npermitopen > 0 &&
(options.allow_tcp_forwarding & FORWARD_LOCAL) != 0;
int do_permitlisten = opts->npermitlisten > 0 &&
(options.allow_tcp_forwarding & FORWARD_REMOTE) != 0;
size_t i;
char msg[1024], buf[64];
snprintf(buf, sizeof(buf), "%d", opts->force_tun_device);
/* Try to keep this alphabetically sorted */
snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s",
opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
opts->force_command == NULL ? "" : " command",
do_env ? " environment" : "",
opts->valid_before == 0 ? "" : "expires",
do_permitopen ? " permitopen" : "",
do_permitlisten ? " permitlisten" : "",
opts->permit_port_forwarding_flag ? " port-forwarding" : "",
opts->cert_principals == NULL ? "" : " principals",
opts->permit_pty_flag ? " pty" : "",
opts->force_tun_device == -1 ? "" : " tun=",
opts->force_tun_device == -1 ? "" : buf,
opts->permit_user_rc ? " user-rc" : "",
opts->permit_x11_forwarding_flag ? " x11-forwarding" : "");
debug("%s: %s", loc, msg);
if (do_remote)
auth_debug_add("%s: %s", loc, msg);
if (options.permit_user_env) {
for (i = 0; i < opts->nenv; i++) {
debug("%s: environment: %s", loc, opts->env[i]);
if (do_remote) {
auth_debug_add("%s: environment: %s",
loc, opts->env[i]);
}
}
}
/* Go into a little more details for the local logs. */
if (opts->valid_before != 0) {
format_absolute_time(opts->valid_before, buf, sizeof(buf));
debug("%s: expires at %s", loc, buf);
}
if (opts->cert_principals != NULL) {
debug("%s: authorized principals: \"%s\"",
loc, opts->cert_principals);
}
if (opts->force_command != NULL)
debug("%s: forced command: \"%s\"", loc, opts->force_command);
if (do_permitopen) {
for (i = 0; i < opts->npermitopen; i++) {
debug("%s: permitted open: %s",
loc, opts->permitopen[i]);
}
}
if (do_permitlisten) {
for (i = 0; i < opts->npermitlisten; i++) {
debug("%s: permitted listen: %s",
loc, opts->permitlisten[i]);
}
}
}
/* Activate a new set of key/cert options; merging with what is there. */
int
auth_activate_options(struct ssh *ssh, struct sshauthopt *opts)
{
struct sshauthopt *old = auth_opts;
const char *emsg = NULL;
debug("%s: setting new authentication options", __func__);
if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) {
error("Inconsistent authentication options: %s", emsg);
return -1;
}
return 0;
}
/* Disable forwarding, etc for the session */
void
auth_restrict_session(struct ssh *ssh)
{
struct sshauthopt *restricted;
debug("%s: restricting session", __func__);
/* A blank sshauthopt defaults to permitting nothing */
restricted = sshauthopt_new();
restricted->permit_pty_flag = 1;
restricted->restricted = 1;
if (auth_activate_options(ssh, restricted) != 0)
fatal("%s: failed to restrict session", __func__);
sshauthopt_free(restricted);
}
int
auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw,
struct sshauthopt *opts, int allow_cert_authority, const char *loc)
{
const char *remote_ip = ssh_remote_ipaddr(ssh);
const char *remote_host = auth_get_canonical_hostname(ssh,
options.use_dns);
time_t now = time(NULL);
char buf[64];
/*
* Check keys/principals file expiry time.
* NB. validity interval in certificate is handled elsewhere.
*/
if (opts->valid_before && now > 0 &&
opts->valid_before < (uint64_t)now) {
format_absolute_time(opts->valid_before, buf, sizeof(buf));
debug("%s: entry expired at %s", loc, buf);
auth_debug_add("%s: entry expired at %s", loc, buf);
return -1;
}
/* Consistency checks */
if (opts->cert_principals != NULL && !opts->cert_authority) {
debug("%s: principals on non-CA key", loc);
auth_debug_add("%s: principals on non-CA key", loc);
/* deny access */
return -1;
}
/* cert-authority flag isn't valid in authorized_principals files */
if (!allow_cert_authority && opts->cert_authority) {
debug("%s: cert-authority flag invalid here", loc);
auth_debug_add("%s: cert-authority flag invalid here", loc);
/* deny access */
return -1;
}
/* Perform from= checks */
if (opts->required_from_host_keys != NULL) {
switch (match_host_and_ip(remote_host, remote_ip,
opts->required_from_host_keys )) {
case 1:
/* Host name matches. */
break;
case -1:
default:
debug("%s: invalid from criteria", loc);
auth_debug_add("%s: invalid from criteria", loc);
/* FALLTHROUGH */
case 0:
logit("%s: Authentication tried for %.100s with "
"correct key but not from a permitted "
"host (host=%.200s, ip=%.200s, required=%.200s).",
loc, pw->pw_name, remote_host, remote_ip,
opts->required_from_host_keys);
auth_debug_add("%s: Your host '%.200s' is not "
"permitted to use this key for login.",
loc, remote_host);
/* deny access */
return -1;
}
}
/* Check source-address restriction from certificate */
if (opts->required_from_host_cert != NULL) {
switch (addr_match_cidr_list(remote_ip,
opts->required_from_host_cert)) {
case 1:
/* accepted */
break;
case -1:
default:
/* invalid */
error("%s: Certificate source-address invalid",
loc);
/* FALLTHROUGH */
case 0:
logit("%s: Authentication tried for %.100s with valid "
"certificate but not from a permitted source "
"address (%.200s).", loc, pw->pw_name, remote_ip);
auth_debug_add("%s: Your address '%.200s' is not "
"permitted to use this certificate for login.",
loc, remote_ip);
return -1;
}
}
/*
*
* XXX this is spammy. We should report remotely only for keys
* that are successful in actual auth attempts, and not PK_OK
* tests.
*/
auth_log_authopts(loc, opts, 1);
return 0;
}
diff --git a/auth.h b/auth.h
index 977562f0a6f3..bf393e75537c 100644
--- a/auth.h
+++ b/auth.h
@@ -1,244 +1,242 @@
-/* $OpenBSD: auth.h,v 1.96 2018/04/10 00:10:49 djm Exp $ */
+/* $OpenBSD: auth.h,v 1.99 2019/01/19 21:43:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AUTH_H
#define AUTH_H
#include <signal.h>
#include <openssl/rsa.h>
#ifdef HAVE_LOGIN_CAP
#include <login_cap.h>
#endif
#ifdef BSD_AUTH
#include <bsd_auth.h>
#endif
#ifdef KRB5
#include <krb5.h>
#endif
struct passwd;
struct ssh;
struct sshbuf;
struct sshkey;
struct sshauthopt;
typedef struct Authctxt Authctxt;
typedef struct Authmethod Authmethod;
typedef struct KbdintDevice KbdintDevice;
struct Authctxt {
sig_atomic_t success;
int authenticated; /* authenticated and alarms cancelled */
int postponed; /* authentication needs another step */
int valid; /* user exists and is allowed to login */
int attempt;
int failures;
int server_caused_failure;
int force_pwchange;
char *user; /* username sent by the client */
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
/* Method lists for multiple authentication */
char **auth_methods; /* modified from server config */
u_int num_auth_methods;
/* Authentication method-specific data */
void *methoddata;
void *kbdintctxt;
#ifdef BSD_AUTH
auth_session_t *as;
#endif
#ifdef KRB5
krb5_context krb5_ctx;
krb5_ccache krb5_fwd_ccache;
krb5_principal krb5_user;
char *krb5_ticket_file;
char *krb5_ccname;
#endif
struct sshbuf *loginmsg;
/* Authentication keys already used; these will be refused henceforth */
struct sshkey **prev_keys;
u_int nprev_keys;
/* Last used key and ancillary information from active auth method */
struct sshkey *auth_method_key;
char *auth_method_info;
/* Information exposed to session */
struct sshbuf *session_info; /* Auth info for environment */
};
/*
* Every authentication method has to handle authentication requests for
* non-existing users, or for users that are not allowed to login. In this
* case 'valid' is set to 0, but 'user' points to the username requested by
* the client.
*/
struct Authmethod {
char *name;
int (*userauth)(struct ssh *);
int *enabled;
};
/*
* Keyboard interactive device:
* init_ctx returns: non NULL upon success
* query returns: 0 - success, otherwise failure
* respond returns: 0 - success, 1 - need further interaction,
* otherwise - failure
*/
struct KbdintDevice
{
const char *name;
void* (*init_ctx)(Authctxt*);
int (*query)(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on);
int (*respond)(void *ctx, u_int numresp, char **responses);
void (*free_ctx)(void *ctx);
};
int
auth_rhosts2(struct passwd *, const char *, const char *, const char *);
int auth_password(struct ssh *, const char *);
-int hostbased_key_allowed(struct passwd *, const char *, char *,
- struct sshkey *);
+int hostbased_key_allowed(struct ssh *, struct passwd *,
+ const char *, char *, struct sshkey *);
int user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
struct sshauthopt **);
int auth2_key_already_used(Authctxt *, const struct sshkey *);
/*
* Handling auth method-specific information for logging and prevention
* of key reuse during multiple authentication.
*/
void auth2_authctxt_reset_info(Authctxt *);
void auth2_record_key(Authctxt *, int, const struct sshkey *);
void auth2_record_info(Authctxt *authctxt, const char *, ...)
__attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2)));
void auth2_update_session_info(Authctxt *, const char *, const char *);
#ifdef KRB5
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
int auth_krb5_password(Authctxt *authctxt, const char *password);
void krb5_cleanup_proc(Authctxt *authctxt);
#endif /* KRB5 */
#if defined(USE_SHADOW) && defined(HAS_SHADOW_EXPIRE)
#include <shadow.h>
int auth_shadow_acctexpired(struct spwd *);
int auth_shadow_pwexpired(Authctxt *);
#endif
#include "auth-pam.h"
#include "audit.h"
void remove_kbdint_device(const char *);
-void do_authentication2(Authctxt *);
+void do_authentication2(struct ssh *);
-void auth_log(Authctxt *, int, int, const char *, const char *);
-void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
+void auth_log(struct ssh *, int, int, const char *, const char *);
+void auth_maxtries_exceeded(struct ssh *) __attribute__((noreturn));
void userauth_finish(struct ssh *, int, const char *, const char *);
int auth_root_allowed(struct ssh *, const char *);
-void userauth_send_banner(const char *);
-
char *auth2_read_banner(void);
int auth2_methods_valid(const char *, int);
int auth2_update_methods_lists(Authctxt *, const char *, const char *);
int auth2_setup_methods_lists(Authctxt *);
int auth2_method_allowed(Authctxt *, const char *, const char *);
void privsep_challenge_enable(void);
int auth2_challenge(struct ssh *, char *);
void auth2_challenge_stop(struct ssh *);
int bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int bsdauth_respond(void *, u_int, char **);
-int allowed_user(struct passwd *);
-struct passwd * getpwnamallow(const char *user);
+int allowed_user(struct ssh *, struct passwd *);
+struct passwd * getpwnamallow(struct ssh *, const char *user);
char *expand_authorized_keys(const char *, struct passwd *pw);
char *authorized_principals_file(struct passwd *);
FILE *auth_openkeyfile(const char *, struct passwd *, int);
FILE *auth_openprincipals(const char *, struct passwd *, int);
int auth_key_is_revoked(struct sshkey *);
const char *auth_get_canonical_hostname(struct ssh *, int);
HostStatus
check_key_in_hostfiles(struct passwd *, struct sshkey *, const char *,
const char *, const char *);
/* hostkey handling */
struct sshkey *get_hostkey_by_index(int);
struct sshkey *get_hostkey_public_by_index(int, struct ssh *);
struct sshkey *get_hostkey_public_by_type(int, int, struct ssh *);
struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *);
int get_hostkey_index(struct sshkey *, int, struct ssh *);
-int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **,
- size_t *, const u_char *, size_t, const char *, u_int);
+int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *,
+ u_char **, size_t *, const u_char *, size_t, const char *);
/* Key / cert options linkage to auth layer */
const struct sshauthopt *auth_options(struct ssh *);
int auth_activate_options(struct ssh *, struct sshauthopt *);
void auth_restrict_session(struct ssh *);
int auth_authorise_keyopts(struct ssh *, struct passwd *pw,
struct sshauthopt *, int, const char *);
void auth_log_authopts(const char *, const struct sshauthopt *, int);
/* debug messages during authentication */
void auth_debug_add(const char *fmt,...)
__attribute__((format(printf, 1, 2)));
-void auth_debug_send(void);
+void auth_debug_send(struct ssh *);
void auth_debug_reset(void);
struct passwd *fakepw(void);
#define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */
#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
pid_t subprocess(const char *, struct passwd *,
const char *, int, char **, FILE **, u_int flags);
int sys_auth_passwd(struct ssh *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
#include <krb5.h>
krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *);
#endif
#endif
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 764ceff74ee6..0c40fad4ed31 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,261 +1,261 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.38 2018/09/20 03:28:06 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.40 2019/01/19 21:43:56 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <string.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "canohost.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "pathnames.h"
#include "ssherr.h"
#include "match.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
static int
userauth_hostbased(struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
struct sshbuf *b;
struct sshkey *key = NULL;
char *pkalg, *cuser, *chost;
u_char *pkblob, *sig;
size_t alen, blen, slen;
int r, pktype, authenticated = 0;
/* XXX use sshkey_froms() */
if ((r = sshpkt_get_cstring(ssh, &pkalg, &alen)) != 0 ||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
(r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &sig, &slen)) != 0)
fatal("%s: packet parsing: %s", __func__, ssh_err(r));
debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__,
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
sshbuf_dump_data(sig, slen, stderr);
#endif
pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
logit("%s: unsupported public key algorithm: %s",
__func__, pkalg);
goto done;
}
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
error("%s: key_from_blob: %s", __func__, ssh_err(r));
goto done;
}
if (key == NULL) {
error("%s: cannot decode key: %s", __func__, pkalg);
goto done;
}
if (key->type != pktype) {
error("%s: type mismatch for decoded key "
"(received %d, expected %d)", __func__, key->type, pktype);
goto done;
}
if (sshkey_type_plain(key->type) == KEY_RSA &&
(ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
error("Refusing RSA key because peer uses unsafe "
"signature format");
goto done;
}
if (match_pattern_list(pkalg, options.hostbased_key_types, 0) != 1) {
logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
__func__, sshkey_type(key));
goto done;
}
if ((r = sshkey_check_cert_sigtype(key,
options.ca_sign_algorithms)) != 0) {
logit("%s: certificate signature algorithm %s: %s", __func__,
(key->cert == NULL || key->cert->signature_type == NULL) ?
"(null)" : key->cert->signature_type, ssh_err(r));
goto done;
}
if (!authctxt->valid || authctxt->user == NULL) {
debug2("%s: disabled because of invalid user", __func__);
goto done;
}
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* reconstruct packet */
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
(r = sshbuf_put_cstring(b, "hostbased")) != 0 ||
(r = sshbuf_put_string(b, pkalg, alen)) != 0 ||
(r = sshbuf_put_string(b, pkblob, blen)) != 0 ||
(r = sshbuf_put_cstring(b, chost)) != 0 ||
(r = sshbuf_put_cstring(b, cuser)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
auth2_record_info(authctxt,
"client user \"%.100s\", client host \"%.100s\"", cuser, chost);
/* test for allowed key and correct signature */
authenticated = 0;
- if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
+ if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser,
+ chost, key)) &&
PRIVSEP(sshkey_verify(key, sig, slen,
sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0)
authenticated = 1;
auth2_record_key(authctxt, authenticated, key);
sshbuf_free(b);
done:
debug2("%s: authenticated %d", __func__, authenticated);
sshkey_free(key);
free(pkalg);
free(pkblob);
free(cuser);
free(chost);
free(sig);
return authenticated;
}
/* return 1 if given hostkey is allowed */
int
-hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
- struct sshkey *key)
+hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
+ const char *cuser, char *chost, struct sshkey *key)
{
- struct ssh *ssh = active_state; /* XXX */
const char *resolvedname, *ipaddr, *lookup, *reason;
HostStatus host_status;
int len;
char *fp;
if (auth_key_is_revoked(key))
return 0;
resolvedname = auth_get_canonical_hostname(ssh, options.use_dns);
ipaddr = ssh_remote_ipaddr(ssh);
debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
chost, resolvedname, ipaddr);
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
debug2("stripping trailing dot from chost %s", chost);
chost[len - 1] = '\0';
}
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0) {
debug2("%s: auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" (from packet)",
__func__, cuser, chost);
return 0;
}
lookup = chost;
} else {
if (strcasecmp(resolvedname, chost) != 0)
logit("userauth_hostbased mismatch: "
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) {
debug2("%s: auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" addr \"%.100s\"",
__func__, cuser, resolvedname, ipaddr);
return 0;
}
lookup = resolvedname;
}
debug2("%s: access allowed by auth_rhosts2", __func__);
if (sshkey_is_cert(key) &&
sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) {
error("%s", reason);
auth_debug_add("%s", reason);
return 0;
}
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE,
options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
/* backward compat if no key has been found. */
if (host_status == HOST_NEW) {
host_status = check_key_in_hostfiles(pw, key, lookup,
_PATH_SSH_SYSTEM_HOSTFILE2,
options.ignore_user_known_hosts ? NULL :
_PATH_SSH_USER_HOSTFILE2);
}
if (host_status == HOST_OK) {
if (sshkey_is_cert(key)) {
if ((fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
sshkey_type(key->cert->signature_key), fp,
cuser, lookup);
} else {
if ((fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
verbose("Accepted %s public key %s from %s@%s",
sshkey_type(key), fp, cuser, lookup);
}
free(fp);
}
return (host_status == HOST_OK);
}
Authmethod method_hostbased = {
"hostbased",
userauth_hostbased,
&options.hostbased_authentication
};
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 2fb5950ea608..0b3975a74d2c 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,1045 +1,1061 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.86 2018/09/20 03:28:06 djm Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.87 2019/01/22 11:26:16 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "packet.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "pathnames.h"
#include "uidswap.h"
#include "auth-options.h"
#include "canohost.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "authfile.h"
#include "match.h"
#include "ssherr.h"
#include "channels.h" /* XXX for session.h */
#include "session.h" /* XXX for child_set_env(); refactor? */
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
static char *
format_key(const struct sshkey *key)
{
char *ret, *fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT);
xasprintf(&ret, "%s %s", sshkey_type(key), fp);
free(fp);
return ret;
}
static int
userauth_pubkey(struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
struct passwd *pw = authctxt->pw;
struct sshbuf *b = NULL;
struct sshkey *key = NULL;
char *pkalg = NULL, *userstyle = NULL, *key_s = NULL, *ca_s = NULL;
u_char *pkblob = NULL, *sig = NULL, have_sig;
size_t blen, slen;
int r, pktype;
int authenticated = 0;
struct sshauthopt *authopts = NULL;
if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
(r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
fatal("%s: parse request failed: %s", __func__, ssh_err(r));
+
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG2) {
+ char *keystring;
+ struct sshbuf *pkbuf;
+
+ if ((pkbuf = sshbuf_from(pkblob, blen)) == NULL)
+ fatal("%s: sshbuf_from failed", __func__);
+ if ((keystring = sshbuf_dtob64(pkbuf)) == NULL)
+ fatal("%s: sshbuf_dtob64 failed", __func__);
+ debug2("%s: %s user %s %s public key %s %s", __func__,
+ authctxt->valid ? "valid" : "invalid", authctxt->user,
+ have_sig ? "attempting" : "querying", pkalg, keystring);
+ sshbuf_free(pkbuf);
+ free(keystring);
+ }
+
pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
verbose("%s: unsupported public key algorithm: %s",
__func__, pkalg);
goto done;
}
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
error("%s: could not parse key: %s", __func__, ssh_err(r));
goto done;
}
if (key == NULL) {
error("%s: cannot decode key: %s", __func__, pkalg);
goto done;
}
if (key->type != pktype) {
error("%s: type mismatch for decoded key "
"(received %d, expected %d)", __func__, key->type, pktype);
goto done;
}
if (sshkey_type_plain(key->type) == KEY_RSA &&
(ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
logit("Refusing RSA key because client uses unsafe "
"signature scheme");
goto done;
}
if (auth2_key_already_used(authctxt, key)) {
logit("refusing previously-used %s key", sshkey_type(key));
goto done;
}
if (match_pattern_list(pkalg, options.pubkey_key_types, 0) != 1) {
logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
__func__, sshkey_ssh_name(key));
goto done;
}
if ((r = sshkey_check_cert_sigtype(key,
options.ca_sign_algorithms)) != 0) {
logit("%s: certificate signature algorithm %s: %s", __func__,
(key->cert == NULL || key->cert->signature_type == NULL) ?
"(null)" : key->cert->signature_type, ssh_err(r));
goto done;
}
key_s = format_key(key);
if (sshkey_is_cert(key))
ca_s = format_key(key->cert->signature_key);
if (have_sig) {
debug3("%s: have %s signature for %s%s%s",
__func__, pkalg, key_s,
ca_s == NULL ? "" : " CA ",
ca_s == NULL ? "" : ca_s);
if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (ssh->compat & SSH_OLD_SESSIONID) {
if ((r = sshbuf_put(b, session_id2,
session_id2_len)) != 0)
fatal("%s: sshbuf_put session id: %s",
__func__, ssh_err(r));
} else {
if ((r = sshbuf_put_string(b, session_id2,
session_id2_len)) != 0)
fatal("%s: sshbuf_put_string session id: %s",
__func__, ssh_err(r));
}
if (!authctxt->valid || authctxt->user == NULL) {
debug2("%s: disabled because of invalid user",
__func__);
goto done;
}
/* reconstruct packet */
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, userstyle)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
(r = sshbuf_put_cstring(b, "publickey")) != 0 ||
(r = sshbuf_put_u8(b, have_sig)) != 0 ||
(r = sshbuf_put_cstring(b, pkalg)) != 0 ||
(r = sshbuf_put_string(b, pkblob, blen)) != 0)
fatal("%s: build packet failed: %s",
__func__, ssh_err(r));
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
PRIVSEP(sshkey_verify(key, sig, slen,
sshbuf_ptr(b), sshbuf_len(b),
(ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL,
ssh->compat)) == 0) {
authenticated = 1;
}
auth2_record_key(authctxt, authenticated, key);
} else {
debug("%s: test pkalg %s pkblob %s%s%s",
__func__, pkalg, key_s,
ca_s == NULL ? "" : " CA ",
ca_s == NULL ? "" : ca_s);
if ((r = sshpkt_get_end(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
if (!authctxt->valid || authctxt->user == NULL) {
debug2("%s: disabled because of invalid user",
__func__);
goto done;
}
/* XXX fake reply and always send PK_OK ? */
/*
* XXX this allows testing whether a user is allowed
* to login: if you happen to have a valid pubkey this
* message is sent. the message is NEVER sent at all
* if a user is not allowed to login. is this an
* issue? -markus
*/
if (PRIVSEP(user_key_allowed(ssh, pw, key, 0, NULL))) {
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
!= 0 ||
(r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
(r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
authctxt->postponed = 1;
}
}
done:
if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) {
debug("%s: key options inconsistent with existing", __func__);
authenticated = 0;
}
debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
sshbuf_free(b);
sshauthopt_free(authopts);
sshkey_free(key);
free(userstyle);
free(pkalg);
free(pkblob);
free(key_s);
free(ca_s);
free(sig);
return authenticated;
}
static int
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
{
char *result;
u_int i;
/* XXX percent_expand() sequences for authorized_principals? */
for (i = 0; i < cert->nprincipals; i++) {
if ((result = match_list(cert->principals[i],
principal_list, NULL)) != NULL) {
debug3("matched principal from key options \"%.100s\"",
result);
free(result);
return 1;
}
}
return 0;
}
/*
* Process a single authorized_principals format line. Returns 0 and sets
* authoptsp is principal is authorised, -1 otherwise. "loc" is used as a
* log preamble for file/line information.
*/
static int
check_principals_line(struct ssh *ssh, char *cp, const struct sshkey_cert *cert,
const char *loc, struct sshauthopt **authoptsp)
{
u_int i, found = 0;
char *ep, *line_opts;
const char *reason = NULL;
struct sshauthopt *opts = NULL;
if (authoptsp != NULL)
*authoptsp = NULL;
/* Trim trailing whitespace. */
ep = cp + strlen(cp) - 1;
while (ep > cp && (*ep == '\n' || *ep == ' ' || *ep == '\t'))
*ep-- = '\0';
/*
* If the line has internal whitespace then assume it has
* key options.
*/
line_opts = NULL;
if ((ep = strrchr(cp, ' ')) != NULL ||
(ep = strrchr(cp, '\t')) != NULL) {
for (; *ep == ' ' || *ep == '\t'; ep++)
;
line_opts = cp;
cp = ep;
}
if ((opts = sshauthopt_parse(line_opts, &reason)) == NULL) {
debug("%s: bad principals options: %s", loc, reason);
auth_debug_add("%s: bad principals options: %s", loc, reason);
return -1;
}
/* Check principals in cert against those on line */
for (i = 0; i < cert->nprincipals; i++) {
if (strcmp(cp, cert->principals[i]) != 0)
continue;
debug3("%s: matched principal \"%.100s\"",
loc, cert->principals[i]);
found = 1;
}
if (found && authoptsp != NULL) {
*authoptsp = opts;
opts = NULL;
}
sshauthopt_free(opts);
return found ? 0 : -1;
}
static int
process_principals(struct ssh *ssh, FILE *f, const char *file,
const struct sshkey_cert *cert, struct sshauthopt **authoptsp)
{
char loc[256], *line = NULL, *cp, *ep;
size_t linesize = 0;
u_long linenum = 0;
u_int found_principal = 0;
if (authoptsp != NULL)
*authoptsp = NULL;
while (getline(&line, &linesize, f) != -1) {
linenum++;
/* Always consume entire input */
if (found_principal)
continue;
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
/* Skip blank and comment lines. */
if ((ep = strchr(cp, '#')) != NULL)
*ep = '\0';
if (!*cp || *cp == '\n')
continue;
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
if (check_principals_line(ssh, cp, cert, loc, authoptsp) == 0)
found_principal = 1;
}
free(line);
return found_principal;
}
/* XXX remove pw args here and elsewhere once ssh->authctxt is guaranteed */
static int
match_principals_file(struct ssh *ssh, struct passwd *pw, char *file,
struct sshkey_cert *cert, struct sshauthopt **authoptsp)
{
FILE *f;
int success;
if (authoptsp != NULL)
*authoptsp = NULL;
temporarily_use_uid(pw);
debug("trying authorized principals file %s", file);
if ((f = auth_openprincipals(file, pw, options.strict_modes)) == NULL) {
restore_uid();
return 0;
}
success = process_principals(ssh, f, file, cert, authoptsp);
fclose(f);
restore_uid();
return success;
}
/*
* Checks whether principal is allowed in output of command.
* returns 1 if the principal is allowed or 0 otherwise.
*/
static int
match_principals_command(struct ssh *ssh, struct passwd *user_pw,
const struct sshkey *key, struct sshauthopt **authoptsp)
{
struct passwd *runas_pw = NULL;
const struct sshkey_cert *cert = key->cert;
FILE *f = NULL;
int r, ok, found_principal = 0;
int i, ac = 0, uid_swapped = 0;
pid_t pid;
char *tmp, *username = NULL, *command = NULL, **av = NULL;
char *ca_fp = NULL, *key_fp = NULL, *catext = NULL, *keytext = NULL;
char serial_s[16], uidstr[32];
void (*osigchld)(int);
if (authoptsp != NULL)
*authoptsp = NULL;
if (options.authorized_principals_command == NULL)
return 0;
if (options.authorized_principals_command_user == NULL) {
error("No user for AuthorizedPrincipalsCommand specified, "
"skipping");
return 0;
}
/*
* NB. all returns later this function should go via "out" to
* ensure the original SIGCHLD handler is restored properly.
*/
osigchld = signal(SIGCHLD, SIG_DFL);
/* Prepare and verify the user for the command */
username = percent_expand(options.authorized_principals_command_user,
"u", user_pw->pw_name, (char *)NULL);
runas_pw = getpwnam(username);
if (runas_pw == NULL) {
error("AuthorizedPrincipalsCommandUser \"%s\" not found: %s",
username, strerror(errno));
goto out;
}
/* Turn the command into an argument vector */
if (argv_split(options.authorized_principals_command, &ac, &av) != 0) {
error("AuthorizedPrincipalsCommand \"%s\" contains "
"invalid quotes", command);
goto out;
}
if (ac == 0) {
error("AuthorizedPrincipalsCommand \"%s\" yielded no arguments",
command);
goto out;
}
if ((ca_fp = sshkey_fingerprint(cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
error("%s: sshkey_fingerprint failed", __func__);
goto out;
}
if ((key_fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
error("%s: sshkey_fingerprint failed", __func__);
goto out;
}
if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) {
error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
goto out;
}
if ((r = sshkey_to_base64(key, &keytext)) != 0) {
error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
goto out;
}
snprintf(serial_s, sizeof(serial_s), "%llu",
(unsigned long long)cert->serial);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)user_pw->pw_uid);
for (i = 1; i < ac; i++) {
tmp = percent_expand(av[i],
"U", uidstr,
"u", user_pw->pw_name,
"h", user_pw->pw_dir,
"t", sshkey_ssh_name(key),
"T", sshkey_ssh_name(cert->signature_key),
"f", key_fp,
"F", ca_fp,
"k", keytext,
"K", catext,
"i", cert->key_id,
"s", serial_s,
(char *)NULL);
if (tmp == NULL)
fatal("%s: percent_expand failed", __func__);
free(av[i]);
av[i] = tmp;
}
/* Prepare a printable command for logs, etc. */
command = argv_assemble(ac, av);
if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,
ac, av, &f,
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
goto out;
uid_swapped = 1;
temporarily_use_uid(runas_pw);
ok = process_principals(ssh, f, "(command)", cert, authoptsp);
fclose(f);
f = NULL;
if (exited_cleanly(pid, "AuthorizedPrincipalsCommand", command, 0) != 0)
goto out;
/* Read completed successfully */
found_principal = ok;
out:
if (f != NULL)
fclose(f);
signal(SIGCHLD, osigchld);
for (i = 0; i < ac; i++)
free(av[i]);
free(av);
if (uid_swapped)
restore_uid();
free(command);
free(username);
free(ca_fp);
free(key_fp);
free(catext);
free(keytext);
return found_principal;
}
static void
skip_space(char **cpp)
{
char *cp;
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
*cpp = cp;
}
/*
* Advanced *cpp past the end of key options, defined as the first unquoted
* whitespace character. Returns 0 on success or -1 on failure (e.g.
* unterminated quotes).
*/
static int
advance_past_options(char **cpp)
{
char *cp = *cpp;
int quoted = 0;
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
*cpp = cp;
/* return failure for unterminated quotes */
return (*cp == '\0' && quoted) ? -1 : 0;
}
/*
* Check a single line of an authorized_keys-format file. Returns 0 if key
* matches, -1 otherwise. Will return key/cert options via *authoptsp
* on success. "loc" is used as file/line location in log messages.
*/
static int
check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
char *cp, const char *loc, struct sshauthopt **authoptsp)
{
int want_keytype = sshkey_is_cert(key) ? KEY_UNSPEC : key->type;
struct sshkey *found = NULL;
struct sshauthopt *keyopts = NULL, *certopts = NULL, *finalopts = NULL;
char *key_options = NULL, *fp = NULL;
const char *reason = NULL;
int ret = -1;
if (authoptsp != NULL)
*authoptsp = NULL;
if ((found = sshkey_new(want_keytype)) == NULL) {
debug3("%s: keytype %d failed", __func__, want_keytype);
goto out;
}
/* XXX djm: peek at key type in line and skip if unwanted */
if (sshkey_read(found, &cp) != 0) {
/* no key? check for options */
debug2("%s: check options: '%s'", loc, cp);
key_options = cp;
if (advance_past_options(&cp) != 0) {
reason = "invalid key option string";
goto fail_reason;
}
skip_space(&cp);
if (sshkey_read(found, &cp) != 0) {
/* still no key? advance to next line*/
debug2("%s: advance: '%s'", loc, cp);
goto out;
}
}
/* Parse key options now; we need to know if this is a CA key */
if ((keyopts = sshauthopt_parse(key_options, &reason)) == NULL) {
debug("%s: bad key options: %s", loc, reason);
auth_debug_add("%s: bad key options: %s", loc, reason);
goto out;
}
/* Ignore keys that don't match or incorrectly marked as CAs */
if (sshkey_is_cert(key)) {
/* Certificate; check signature key against CA */
if (!sshkey_equal(found, key->cert->signature_key) ||
!keyopts->cert_authority)
goto out;
} else {
/* Plain key: check it against key found in file */
if (!sshkey_equal(found, key) || keyopts->cert_authority)
goto out;
}
/* We have a candidate key, perform authorisation checks */
if ((fp = sshkey_fingerprint(found,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: fingerprint failed", __func__);
debug("%s: matching %s found: %s %s", loc,
sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp);
if (auth_authorise_keyopts(ssh, pw, keyopts,
sshkey_is_cert(key), loc) != 0) {
reason = "Refused by key options";
goto fail_reason;
}
/* That's all we need for plain keys. */
if (!sshkey_is_cert(key)) {
verbose("Accepted key %s %s found at %s",
sshkey_type(found), fp, loc);
finalopts = keyopts;
keyopts = NULL;
goto success;
}
/*
* Additional authorisation for certificates.
*/
/* Parse and check options present in certificate */
if ((certopts = sshauthopt_from_cert(key)) == NULL) {
reason = "Invalid certificate options";
goto fail_reason;
}
if (auth_authorise_keyopts(ssh, pw, certopts, 0, loc) != 0) {
reason = "Refused by certificate options";
goto fail_reason;
}
if ((finalopts = sshauthopt_merge(keyopts, certopts, &reason)) == NULL)
goto fail_reason;
/*
* If the user has specified a list of principals as
* a key option, then prefer that list to matching
* their username in the certificate principals list.
*/
if (keyopts->cert_principals != NULL &&
!match_principals_option(keyopts->cert_principals, key->cert)) {
reason = "Certificate does not contain an authorized principal";
goto fail_reason;
}
if (sshkey_cert_check_authority(key, 0, 0,
keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0)
goto fail_reason;
verbose("Accepted certificate ID \"%s\" (serial %llu) "
"signed by CA %s %s found at %s",
key->cert->key_id,
(unsigned long long)key->cert->serial,
sshkey_type(found), fp, loc);
success:
if (finalopts == NULL)
fatal("%s: internal error: missing options", __func__);
if (authoptsp != NULL) {
*authoptsp = finalopts;
finalopts = NULL;
}
/* success */
ret = 0;
goto out;
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
out:
free(fp);
sshauthopt_free(keyopts);
sshauthopt_free(certopts);
sshauthopt_free(finalopts);
sshkey_free(found);
return ret;
}
/*
* Checks whether key is allowed in authorized_keys-format file,
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
check_authkeys_file(struct ssh *ssh, struct passwd *pw, FILE *f,
char *file, struct sshkey *key, struct sshauthopt **authoptsp)
{
char *cp, *line = NULL, loc[256];
size_t linesize = 0;
int found_key = 0;
u_long linenum = 0;
if (authoptsp != NULL)
*authoptsp = NULL;
while (getline(&line, &linesize, f) != -1) {
linenum++;
/* Always consume entire file */
if (found_key)
continue;
/* Skip leading whitespace, empty and comment lines. */
cp = line;
skip_space(&cp);
if (!*cp || *cp == '\n' || *cp == '#')
continue;
snprintf(loc, sizeof(loc), "%.200s:%lu", file, linenum);
if (check_authkey_line(ssh, pw, key, cp, loc, authoptsp) == 0)
found_key = 1;
}
free(line);
return found_key;
}
/* Authenticate a certificate key against TrustedUserCAKeys */
static int
user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
struct sshauthopt **authoptsp)
{
char *ca_fp, *principals_file = NULL;
const char *reason;
struct sshauthopt *principals_opts = NULL, *cert_opts = NULL;
struct sshauthopt *final_opts = NULL;
int r, ret = 0, found_principal = 0, use_authorized_principals;
if (authoptsp != NULL)
*authoptsp = NULL;
if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL)
return 0;
if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
return 0;
if ((r = sshkey_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1, 0)) != 0) {
debug2("%s: CA %s %s is not listed in %s: %s", __func__,
sshkey_type(key->cert->signature_key), ca_fp,
options.trusted_user_ca_keys, ssh_err(r));
goto out;
}
/*
* If AuthorizedPrincipals is in use, then compare the certificate
* principals against the names in that file rather than matching
* against the username.
*/
if ((principals_file = authorized_principals_file(pw)) != NULL) {
if (match_principals_file(ssh, pw, principals_file,
key->cert, &principals_opts))
found_principal = 1;
}
/* Try querying command if specified */
if (!found_principal && match_principals_command(ssh, pw, key,
&principals_opts))
found_principal = 1;
/* If principals file or command is specified, then require a match */
use_authorized_principals = principals_file != NULL ||
options.authorized_principals_command != NULL;
if (!found_principal && use_authorized_principals) {
reason = "Certificate does not contain an authorized principal";
goto fail_reason;
}
if (use_authorized_principals && principals_opts == NULL)
fatal("%s: internal error: missing principals_opts", __func__);
if (sshkey_cert_check_authority(key, 0, 1,
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
goto fail_reason;
/* Check authority from options in key and from principals file/cmd */
if ((cert_opts = sshauthopt_from_cert(key)) == NULL) {
reason = "Invalid certificate options";
goto fail_reason;
}
if (auth_authorise_keyopts(ssh, pw, cert_opts, 0, "cert") != 0) {
reason = "Refused by certificate options";
goto fail_reason;
}
if (principals_opts == NULL) {
final_opts = cert_opts;
cert_opts = NULL;
} else {
if (auth_authorise_keyopts(ssh, pw, principals_opts, 0,
"principals") != 0) {
reason = "Refused by certificate principals options";
goto fail_reason;
}
if ((final_opts = sshauthopt_merge(principals_opts,
cert_opts, &reason)) == NULL) {
fail_reason:
error("%s", reason);
auth_debug_add("%s", reason);
goto out;
}
}
/* Success */
verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
"%s CA %s via %s", key->cert->key_id,
(unsigned long long)key->cert->serial,
sshkey_type(key->cert->signature_key), ca_fp,
options.trusted_user_ca_keys);
if (authoptsp != NULL) {
*authoptsp = final_opts;
final_opts = NULL;
}
ret = 1;
out:
sshauthopt_free(principals_opts);
sshauthopt_free(cert_opts);
sshauthopt_free(final_opts);
free(principals_file);
free(ca_fp);
return ret;
}
/*
* Checks whether key is allowed in file.
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_allowed2(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
char *file, struct sshauthopt **authoptsp)
{
FILE *f;
int found_key = 0;
if (authoptsp != NULL)
*authoptsp = NULL;
/* Temporarily use the user's uid. */
temporarily_use_uid(pw);
debug("trying public key file %s", file);
if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
found_key = check_authkeys_file(ssh, pw, f, file,
key, authoptsp);
fclose(f);
}
restore_uid();
return found_key;
}
/*
* Checks whether key is allowed in output of command.
* returns 1 if the key is allowed or 0 otherwise.
*/
static int
user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw,
struct sshkey *key, struct sshauthopt **authoptsp)
{
struct passwd *runas_pw = NULL;
FILE *f = NULL;
int r, ok, found_key = 0;
int i, uid_swapped = 0, ac = 0;
pid_t pid;
char *username = NULL, *key_fp = NULL, *keytext = NULL;
char uidstr[32], *tmp, *command = NULL, **av = NULL;
void (*osigchld)(int);
if (authoptsp != NULL)
*authoptsp = NULL;
if (options.authorized_keys_command == NULL)
return 0;
if (options.authorized_keys_command_user == NULL) {
error("No user for AuthorizedKeysCommand specified, skipping");
return 0;
}
/*
* NB. all returns later this function should go via "out" to
* ensure the original SIGCHLD handler is restored properly.
*/
osigchld = signal(SIGCHLD, SIG_DFL);
/* Prepare and verify the user for the command */
username = percent_expand(options.authorized_keys_command_user,
"u", user_pw->pw_name, (char *)NULL);
runas_pw = getpwnam(username);
if (runas_pw == NULL) {
error("AuthorizedKeysCommandUser \"%s\" not found: %s",
username, strerror(errno));
goto out;
}
/* Prepare AuthorizedKeysCommand */
if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
error("%s: sshkey_fingerprint failed", __func__);
goto out;
}
if ((r = sshkey_to_base64(key, &keytext)) != 0) {
error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
goto out;
}
/* Turn the command into an argument vector */
if (argv_split(options.authorized_keys_command, &ac, &av) != 0) {
error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
command);
goto out;
}
if (ac == 0) {
error("AuthorizedKeysCommand \"%s\" yielded no arguments",
command);
goto out;
}
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)user_pw->pw_uid);
for (i = 1; i < ac; i++) {
tmp = percent_expand(av[i],
"U", uidstr,
"u", user_pw->pw_name,
"h", user_pw->pw_dir,
"t", sshkey_ssh_name(key),
"f", key_fp,
"k", keytext,
(char *)NULL);
if (tmp == NULL)
fatal("%s: percent_expand failed", __func__);
free(av[i]);
av[i] = tmp;
}
/* Prepare a printable command for logs, etc. */
command = argv_assemble(ac, av);
/*
* If AuthorizedKeysCommand was run without arguments
* then fall back to the old behaviour of passing the
* target username as a single argument.
*/
if (ac == 1) {
av = xreallocarray(av, ac + 2, sizeof(*av));
av[1] = xstrdup(user_pw->pw_name);
av[2] = NULL;
/* Fix up command too, since it is used in log messages */
free(command);
xasprintf(&command, "%s %s", av[0], av[1]);
}
if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,
ac, av, &f,
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
goto out;
uid_swapped = 1;
temporarily_use_uid(runas_pw);
ok = check_authkeys_file(ssh, user_pw, f,
options.authorized_keys_command, key, authoptsp);
fclose(f);
f = NULL;
if (exited_cleanly(pid, "AuthorizedKeysCommand", command, 0) != 0)
goto out;
/* Read completed successfully */
found_key = ok;
out:
if (f != NULL)
fclose(f);
signal(SIGCHLD, osigchld);
for (i = 0; i < ac; i++)
free(av[i]);
free(av);
if (uid_swapped)
restore_uid();
free(command);
free(username);
free(key_fp);
free(keytext);
return found_key;
}
/*
* Check whether key authenticates and authorises the user.
*/
int
user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
int auth_attempt, struct sshauthopt **authoptsp)
{
u_int success, i;
char *file;
struct sshauthopt *opts = NULL;
if (authoptsp != NULL)
*authoptsp = NULL;
if (auth_key_is_revoked(key))
return 0;
if (sshkey_is_cert(key) &&
auth_key_is_revoked(key->cert->signature_key))
return 0;
if ((success = user_cert_trusted_ca(ssh, pw, key, &opts)) != 0)
goto out;
sshauthopt_free(opts);
opts = NULL;
if ((success = user_key_command_allowed2(ssh, pw, key, &opts)) != 0)
goto out;
sshauthopt_free(opts);
opts = NULL;
for (i = 0; !success && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue;
file = expand_authorized_keys(
options.authorized_keys_files[i], pw);
success = user_key_allowed2(ssh, pw, key, file, &opts);
free(file);
}
out:
if (success && authoptsp != NULL) {
*authoptsp = opts;
opts = NULL;
}
sshauthopt_free(opts);
return success;
}
Authmethod method_pubkey = {
"publickey",
userauth_pubkey,
&options.pubkey_authentication
};
diff --git a/auth2.c b/auth2.c
index 4d19957a6ed3..16ae1a3635e5 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,794 +1,821 @@
-/* $OpenBSD: auth2.c,v 1.149 2018/07/11 18:53:29 markus Exp $ */
+/* $OpenBSD: auth2.c,v 1.155 2019/03/25 22:34:52 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <time.h>
#include "atomicio.h"
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
#include "log.h"
#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "dispatch.h"
#include "pathnames.h"
#include "sshbuf.h"
#include "ssherr.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "ssherr.h"
#include "digest.h"
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
extern struct sshbuf *loginmsg;
/* methods */
extern Authmethod method_none;
extern Authmethod method_pubkey;
extern Authmethod method_passwd;
extern Authmethod method_kbdint;
extern Authmethod method_hostbased;
#ifdef GSSAPI
extern Authmethod method_gssapi;
#endif
Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
#ifdef GSSAPI
&method_gssapi,
#endif
&method_passwd,
&method_kbdint,
&method_hostbased,
NULL
};
/* protocol */
static int input_service_request(int, u_int32_t, struct ssh *);
static int input_userauth_request(int, u_int32_t, struct ssh *);
/* helper */
static Authmethod *authmethod_lookup(Authctxt *, const char *);
static char *authmethods_get(Authctxt *authctxt);
#define MATCH_NONE 0 /* method or submethod mismatch */
#define MATCH_METHOD 1 /* method matches (no submethod specified) */
#define MATCH_BOTH 2 /* method and submethod match */
#define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */
static int list_starts_with(const char *, const char *, const char *);
char *
auth2_read_banner(void)
{
struct stat st;
char *banner = NULL;
size_t len, n;
int fd;
if ((fd = open(options.banner, O_RDONLY)) == -1)
return (NULL);
if (fstat(fd, &st) == -1) {
close(fd);
return (NULL);
}
if (st.st_size <= 0 || st.st_size > 1*1024*1024) {
close(fd);
return (NULL);
}
len = (size_t)st.st_size; /* truncate */
banner = xmalloc(len + 1);
n = atomicio(read, fd, banner, len);
close(fd);
if (n != len) {
free(banner);
return (NULL);
}
banner[n] = '\0';
return (banner);
}
-void
-userauth_send_banner(const char *msg)
+static void
+userauth_send_banner(struct ssh *ssh, const char *msg)
{
- packet_start(SSH2_MSG_USERAUTH_BANNER);
- packet_put_cstring(msg);
- packet_put_cstring(""); /* language, unused */
- packet_send();
+ int r;
+
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, msg)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
debug("%s: sent", __func__);
}
static void
-userauth_banner(void)
+userauth_banner(struct ssh *ssh)
{
char *banner = NULL;
if (options.banner == NULL)
return;
if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
goto done;
- userauth_send_banner(banner);
+ userauth_send_banner(ssh, banner);
done:
free(banner);
}
/*
* loop until authctxt->success == TRUE
*/
void
-do_authentication2(Authctxt *authctxt)
+do_authentication2(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
- ssh->authctxt = authctxt; /* XXX move to caller */
+ Authctxt *authctxt = ssh->authctxt;
+
ssh_dispatch_init(ssh, &dispatch_protocol_error);
ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request);
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success);
ssh->authctxt = NULL;
}
/*ARGSUSED*/
static int
input_service_request(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
- u_int len;
- int acceptit = 0;
- char *service = packet_get_cstring(&len);
- packet_check_eom();
+ char *service = NULL;
+ int r, acceptit = 0;
+
+ if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
if (authctxt == NULL)
fatal("input_service_request: no authctxt");
if (strcmp(service, "ssh-userauth") == 0) {
if (!authctxt->success) {
acceptit = 1;
/* now we can handle user-auth requests */
- ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST,
+ &input_userauth_request);
}
}
/* XXX all other service requests are denied */
if (acceptit) {
- packet_start(SSH2_MSG_SERVICE_ACCEPT);
- packet_put_cstring(service);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, service)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ goto out;
} else {
debug("bad service request %s", service);
- packet_disconnect("bad service request %s", service);
+ ssh_packet_disconnect(ssh, "bad service request %s", service);
}
+ r = 0;
+ out:
free(service);
return 0;
}
#define MIN_FAIL_DELAY_SECONDS 0.005
static double
user_specific_delay(const char *user)
{
char b[512];
size_t len = ssh_digest_bytes(SSH_DIGEST_SHA512);
u_char *hash = xmalloc(len);
double delay;
(void)snprintf(b, sizeof b, "%llu%s",
(unsigned long long)options.timing_secret, user);
if (ssh_digest_memory(SSH_DIGEST_SHA512, b, strlen(b), hash, len) != 0)
fatal("%s: ssh_digest_memory", __func__);
/* 0-4.2 ms of delay */
delay = (double)PEEK_U32(hash) / 1000 / 1000 / 1000 / 1000;
freezero(hash, len);
debug3("%s: user specific delay %0.3lfms", __func__, delay/1000);
return MIN_FAIL_DELAY_SECONDS + delay;
}
static void
ensure_minimum_time_since(double start, double seconds)
{
struct timespec ts;
double elapsed = monotime_double() - start, req = seconds, remain;
/* if we've already passed the requested time, scale up */
while ((remain = seconds - elapsed) < 0.0)
seconds *= 2;
ts.tv_sec = remain;
ts.tv_nsec = (remain - ts.tv_sec) * 1000000000;
debug3("%s: elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)",
__func__, elapsed*1000, remain*1000, req*1000);
nanosleep(&ts, NULL);
}
/*ARGSUSED*/
static int
input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
Authmethod *m = NULL;
- char *user, *service, *method, *style = NULL;
- int authenticated = 0;
+ char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
+ int r, authenticated = 0;
double tstart = monotime_double();
if (authctxt == NULL)
fatal("input_userauth_request: no authctxt");
- user = packet_get_cstring(NULL);
- service = packet_get_cstring(NULL);
- method = packet_get_cstring(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0)
+ goto out;
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
if (authctxt->attempt++ == 0) {
/* setup auth context */
- authctxt->pw = PRIVSEP(getpwnamallow(user));
+ authctxt->pw = PRIVSEP(getpwnamallow(ssh, user));
authctxt->user = xstrdup(user);
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
debug2("%s: setting up authctxt for %s",
__func__, user);
} else {
/* Invalid user, fake password information */
authctxt->pw = fakepw();
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_INVALID_USER));
+ PRIVSEP(audit_event(ssh, SSH_INVALID_USER));
#endif
}
#ifdef USE_PAM
if (options.use_pam)
- PRIVSEP(start_pam(authctxt));
+ PRIVSEP(start_pam(ssh));
#endif
ssh_packet_set_log_preamble(ssh, "%suser %s",
authctxt->valid ? "authenticating " : "invalid ", user);
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
if (use_privsep)
mm_inform_authserv(service, style);
- userauth_banner();
+ userauth_banner(ssh);
if (auth2_setup_methods_lists(authctxt) != 0)
- packet_disconnect("no authentication methods enabled");
+ ssh_packet_disconnect(ssh,
+ "no authentication methods enabled");
} else if (strcmp(user, authctxt->user) != 0 ||
strcmp(service, authctxt->service) != 0) {
- packet_disconnect("Change of username or service not allowed: "
- "(%s,%s) -> (%s,%s)",
+ ssh_packet_disconnect(ssh, "Change of username or service "
+ "not allowed: (%s,%s) -> (%s,%s)",
authctxt->user, authctxt->service, user, service);
}
/* reset state */
auth2_challenge_stop(ssh);
#ifdef GSSAPI
/* XXX move to auth2_gssapi_stop() */
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
#endif
auth2_authctxt_reset_info(authctxt);
authctxt->postponed = 0;
authctxt->server_caused_failure = 0;
/* try to authenticate user */
m = authmethod_lookup(authctxt, method);
if (m != NULL && authctxt->failures < options.max_authtries) {
debug2("input_userauth_request: try method %s", method);
authenticated = m->userauth(ssh);
}
if (!authctxt->authenticated)
ensure_minimum_time_since(tstart,
user_specific_delay(authctxt->user));
userauth_finish(ssh, authenticated, method, NULL);
-
+ r = 0;
+ out:
free(service);
free(user);
free(method);
- return 0;
+ return r;
}
void
userauth_finish(struct ssh *ssh, int authenticated, const char *method,
const char *submethod)
{
Authctxt *authctxt = ssh->authctxt;
char *methods;
- int partial = 0;
+ int r, partial = 0;
if (!authctxt->valid && authenticated)
fatal("INTERNAL ERROR: authenticated invalid user %s",
authctxt->user);
if (authenticated && authctxt->postponed)
fatal("INTERNAL ERROR: authenticated and postponed");
/* Special handling for root */
if (authenticated && authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(ssh, method)) {
authenticated = 0;
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
+ PRIVSEP(audit_event(ssh, SSH_LOGIN_ROOT_DENIED));
#endif
}
if (authenticated && options.num_auth_methods != 0) {
if (!auth2_update_methods_lists(authctxt, method, submethod)) {
authenticated = 0;
partial = 1;
}
}
/* Log before sending the reply */
- auth_log(authctxt, authenticated, partial, method, submethod);
+ auth_log(ssh, authenticated, partial, method, submethod);
/* Update information exposed to session */
if (authenticated || partial)
auth2_update_session_info(authctxt, method, submethod);
if (authctxt->postponed)
return;
#ifdef USE_PAM
if (options.use_pam && authenticated) {
int r;
if (!PRIVSEP(do_pam_account())) {
/* if PAM returned a message, send it to the user */
if (sshbuf_len(loginmsg) > 0) {
if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
- userauth_send_banner(sshbuf_ptr(loginmsg));
- packet_write_wait();
+ userauth_send_banner(ssh, sshbuf_ptr(loginmsg));
+ if ((r = ssh_packet_write_wait(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: send PAM banner", __func__);
+ }
}
fatal("Access denied for user %s by PAM account "
"configuration", authctxt->user);
}
}
#endif
if (authenticated == 1) {
/* turn off userauth */
- ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
- packet_start(SSH2_MSG_USERAUTH_SUCCESS);
- packet_send();
- packet_write_wait();
+ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST,
+ &dispatch_protocol_ignore);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
/* now we can break out */
authctxt->success = 1;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
} else {
/* Allow initial try of "none" auth without failure penalty */
if (!partial && !authctxt->server_caused_failure &&
(authctxt->attempt > 1 || strcmp(method, "none") != 0))
authctxt->failures++;
if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
+ PRIVSEP(audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES));
#endif
- auth_maxtries_exceeded(authctxt);
+ auth_maxtries_exceeded(ssh);
}
methods = authmethods_get(authctxt);
debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
partial, methods);
- packet_start(SSH2_MSG_USERAUTH_FAILURE);
- packet_put_cstring(methods);
- packet_put_char(partial);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, methods)) != 0 ||
+ (r = sshpkt_put_u8(ssh, partial)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
free(methods);
}
}
/*
* Checks whether method is allowed by at least one AuthenticationMethods
* methods list. Returns 1 if allowed, or no methods lists configured.
* 0 otherwise.
*/
int
auth2_method_allowed(Authctxt *authctxt, const char *method,
const char *submethod)
{
u_int i;
/*
* NB. authctxt->num_auth_methods might be zero as a result of
* auth2_setup_methods_lists(), so check the configuration.
*/
if (options.num_auth_methods == 0)
return 1;
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (list_starts_with(authctxt->auth_methods[i], method,
submethod) != MATCH_NONE)
return 1;
}
return 0;
}
static char *
authmethods_get(Authctxt *authctxt)
{
struct sshbuf *b;
char *list;
int i, r;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0)
continue;
if (!auth2_method_allowed(authctxt, authmethods[i]->name,
NULL))
continue;
if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "",
authmethods[i]->name)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if ((list = sshbuf_dup_string(b)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
sshbuf_free(b);
return list;
}
static Authmethod *
authmethod_lookup(Authctxt *authctxt, const char *name)
{
int i;
if (name != NULL)
for (i = 0; authmethods[i] != NULL; i++)
if (authmethods[i]->enabled != NULL &&
*(authmethods[i]->enabled) != 0 &&
strcmp(name, authmethods[i]->name) == 0 &&
auth2_method_allowed(authctxt,
authmethods[i]->name, NULL))
return authmethods[i];
debug2("Unrecognized authentication method name: %s",
name ? name : "NULL");
return NULL;
}
/*
* Check a comma-separated list of methods for validity. Is need_enable is
* non-zero, then also require that the methods are enabled.
* Returns 0 on success or -1 if the methods list is invalid.
*/
int
auth2_methods_valid(const char *_methods, int need_enable)
{
char *methods, *omethods, *method, *p;
u_int i, found;
int ret = -1;
if (*_methods == '\0') {
error("empty authentication method list");
return -1;
}
omethods = methods = xstrdup(_methods);
while ((method = strsep(&methods, ",")) != NULL) {
for (found = i = 0; !found && authmethods[i] != NULL; i++) {
if ((p = strchr(method, ':')) != NULL)
*p = '\0';
if (strcmp(method, authmethods[i]->name) != 0)
continue;
if (need_enable) {
if (authmethods[i]->enabled == NULL ||
*(authmethods[i]->enabled) == 0) {
error("Disabled method \"%s\" in "
"AuthenticationMethods list \"%s\"",
method, _methods);
goto out;
}
}
found = 1;
break;
}
if (!found) {
error("Unknown authentication method \"%s\" in list",
method);
goto out;
}
}
ret = 0;
out:
free(omethods);
return ret;
}
/*
* Prune the AuthenticationMethods supplied in the configuration, removing
* any methods lists that include disabled methods. Note that this might
* leave authctxt->num_auth_methods == 0, even when multiple required auth
* has been requested. For this reason, all tests for whether multiple is
* enabled should consult options.num_auth_methods directly.
*/
int
auth2_setup_methods_lists(Authctxt *authctxt)
{
u_int i;
+ /* First, normalise away the "any" pseudo-method */
+ if (options.num_auth_methods == 1 &&
+ strcmp(options.auth_methods[0], "any") == 0) {
+ free(options.auth_methods[0]);
+ options.auth_methods[0] = NULL;
+ options.num_auth_methods = 0;
+ }
+
if (options.num_auth_methods == 0)
return 0;
debug3("%s: checking methods", __func__);
authctxt->auth_methods = xcalloc(options.num_auth_methods,
sizeof(*authctxt->auth_methods));
authctxt->num_auth_methods = 0;
for (i = 0; i < options.num_auth_methods; i++) {
if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
logit("Authentication methods list \"%s\" contains "
"disabled method, skipping",
options.auth_methods[i]);
continue;
}
debug("authentication methods list %d: %s",
authctxt->num_auth_methods, options.auth_methods[i]);
authctxt->auth_methods[authctxt->num_auth_methods++] =
xstrdup(options.auth_methods[i]);
}
if (authctxt->num_auth_methods == 0) {
error("No AuthenticationMethods left after eliminating "
"disabled methods");
return -1;
}
return 0;
}
static int
list_starts_with(const char *methods, const char *method,
const char *submethod)
{
size_t l = strlen(method);
int match;
const char *p;
if (strncmp(methods, method, l) != 0)
return MATCH_NONE;
p = methods + l;
match = MATCH_METHOD;
if (*p == ':') {
if (!submethod)
return MATCH_PARTIAL;
l = strlen(submethod);
p += 1;
if (strncmp(submethod, p, l))
return MATCH_NONE;
p += l;
match = MATCH_BOTH;
}
if (*p != ',' && *p != '\0')
return MATCH_NONE;
return match;
}
/*
* Remove method from the start of a comma-separated list of methods.
* Returns 0 if the list of methods did not start with that method or 1
* if it did.
*/
static int
remove_method(char **methods, const char *method, const char *submethod)
{
char *omethods = *methods, *p;
size_t l = strlen(method);
int match;
match = list_starts_with(omethods, method, submethod);
if (match != MATCH_METHOD && match != MATCH_BOTH)
return 0;
p = omethods + l;
if (submethod && match == MATCH_BOTH)
p += 1 + strlen(submethod); /* include colon */
if (*p == ',')
p++;
*methods = xstrdup(p);
free(omethods);
return 1;
}
/*
* Called after successful authentication. Will remove the successful method
* from the start of each list in which it occurs. If it was the last method
* in any list, then authentication is deemed successful.
* Returns 1 if the method completed any authentication list or 0 otherwise.
*/
int
auth2_update_methods_lists(Authctxt *authctxt, const char *method,
const char *submethod)
{
u_int i, found = 0;
debug3("%s: updating methods list after \"%s\"", __func__, method);
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (!remove_method(&(authctxt->auth_methods[i]), method,
submethod))
continue;
found = 1;
if (*authctxt->auth_methods[i] == '\0') {
debug2("authentication methods list %d complete", i);
return 1;
}
debug3("authentication methods list %d remaining: \"%s\"",
i, authctxt->auth_methods[i]);
}
/* This should not happen, but would be bad if it did */
if (!found)
fatal("%s: method not in AuthenticationMethods", __func__);
return 0;
}
/* Reset method-specific information */
void auth2_authctxt_reset_info(Authctxt *authctxt)
{
sshkey_free(authctxt->auth_method_key);
free(authctxt->auth_method_info);
authctxt->auth_method_key = NULL;
authctxt->auth_method_info = NULL;
}
/* Record auth method-specific information for logs */
void
auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
{
va_list ap;
int i;
free(authctxt->auth_method_info);
authctxt->auth_method_info = NULL;
va_start(ap, fmt);
i = vasprintf(&authctxt->auth_method_info, fmt, ap);
va_end(ap);
if (i < 0 || authctxt->auth_method_info == NULL)
fatal("%s: vasprintf failed", __func__);
}
/*
* Records a public key used in authentication. This is used for logging
* and to ensure that the same key is not subsequently accepted again for
* multiple authentication.
*/
void
auth2_record_key(Authctxt *authctxt, int authenticated,
const struct sshkey *key)
{
struct sshkey **tmp, *dup;
int r;
if ((r = sshkey_from_private(key, &dup)) != 0)
fatal("%s: copy key: %s", __func__, ssh_err(r));
sshkey_free(authctxt->auth_method_key);
authctxt->auth_method_key = dup;
if (!authenticated)
return;
/* If authenticated, make sure we don't accept this key again */
if ((r = sshkey_from_private(key, &dup)) != 0)
fatal("%s: copy key: %s", __func__, ssh_err(r));
if (authctxt->nprev_keys >= INT_MAX ||
(tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
fatal("%s: reallocarray failed", __func__);
authctxt->prev_keys = tmp;
authctxt->prev_keys[authctxt->nprev_keys] = dup;
authctxt->nprev_keys++;
}
/* Checks whether a key has already been previously used for authentication */
int
auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
{
u_int i;
char *fp;
for (i = 0; i < authctxt->nprev_keys; i++) {
if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
fp = sshkey_fingerprint(authctxt->prev_keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT);
debug3("%s: key already used: %s %s", __func__,
sshkey_type(authctxt->prev_keys[i]),
fp == NULL ? "UNKNOWN" : fp);
free(fp);
return 1;
}
}
return 0;
}
/*
* Updates authctxt->session_info with details of authentication. Should be
* whenever an authentication method succeeds.
*/
void
auth2_update_session_info(Authctxt *authctxt, const char *method,
const char *submethod)
{
int r;
if (authctxt->session_info == NULL) {
if ((authctxt->session_info = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
}
/* Append method[/submethod] */
if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
method, submethod == NULL ? "" : "/",
submethod == NULL ? "" : submethod)) != 0)
fatal("%s: append method: %s", __func__, ssh_err(r));
/* Append key if present */
if (authctxt->auth_method_key != NULL) {
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
(r = sshkey_format_text(authctxt->auth_method_key,
authctxt->session_info)) != 0)
fatal("%s: append key: %s", __func__, ssh_err(r));
}
if (authctxt->auth_method_info != NULL) {
/* Ensure no ambiguity here */
if (strchr(authctxt->auth_method_info, '\n') != NULL)
fatal("%s: auth_method_info contains \\n", __func__);
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
(r = sshbuf_putf(authctxt->session_info, "%s",
authctxt->auth_method_info)) != 0) {
fatal("%s: append method info: %s",
__func__, ssh_err(r));
}
}
if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
fatal("%s: append: %s", __func__, ssh_err(r));
}
diff --git a/authfd.c b/authfd.c
index ecdd869abf01..95348abfceca 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,580 +1,582 @@
-/* $OpenBSD: authfd.c,v 1.111 2018/07/09 21:59:10 markus Exp $ */
+/* $OpenBSD: authfd.c,v 1.113 2018/12/27 23:02:11 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for connecting the local authentication agent.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation,
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "xmalloc.h"
#include "ssh.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "authfd.h"
#include "cipher.h"
#include "compat.h"
#include "log.h"
#include "atomicio.h"
#include "misc.h"
#include "ssherr.h"
#define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */
#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */
/* macro to check for "agent failure" message */
#define agent_failed(x) \
((x == SSH_AGENT_FAILURE) || \
(x == SSH_COM_AGENT2_FAILURE) || \
(x == SSH2_AGENT_FAILURE))
/* Convert success/failure response from agent to a err.h status */
static int
decode_reply(u_char type)
{
if (agent_failed(type))
return SSH_ERR_AGENT_FAILURE;
else if (type == SSH_AGENT_SUCCESS)
return 0;
else
return SSH_ERR_INVALID_FORMAT;
}
/* Returns the number of the authentication fd, or -1 if there is none. */
int
ssh_get_authentication_socket(int *fdp)
{
const char *authsocket;
int sock, oerrno;
struct sockaddr_un sunaddr;
if (fdp != NULL)
*fdp = -1;
authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
- if (!authsocket)
+ if (authsocket == NULL || *authsocket == '\0')
return SSH_ERR_AGENT_NOT_PRESENT;
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return SSH_ERR_SYSTEM_ERROR;
/* close on exec */
if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 ||
connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
oerrno = errno;
close(sock);
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
if (fdp != NULL)
*fdp = sock;
else
close(sock);
return 0;
}
/* Communicate with agent: send request and read reply */
static int
ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
{
int r;
size_t l, len;
char buf[1024];
/* Get the length of the message, and format it in the buffer. */
len = sshbuf_len(request);
POKE_U32(buf, len);
/* Send the length and then the packet to the agent. */
if (atomicio(vwrite, sock, buf, 4) != 4 ||
atomicio(vwrite, sock, sshbuf_mutable_ptr(request),
sshbuf_len(request)) != sshbuf_len(request))
return SSH_ERR_AGENT_COMMUNICATION;
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
if (atomicio(read, sock, buf, 4) != 4)
return SSH_ERR_AGENT_COMMUNICATION;
/* Extract the length, and check it for sanity. */
len = PEEK_U32(buf);
if (len > MAX_AGENT_REPLY_LEN)
return SSH_ERR_INVALID_FORMAT;
/* Read the rest of the response in to the buffer. */
sshbuf_reset(reply);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
if (atomicio(read, sock, buf, l) != l)
return SSH_ERR_AGENT_COMMUNICATION;
if ((r = sshbuf_put(reply, buf, l)) != 0)
return r;
len -= l;
}
return 0;
}
/*
* Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by
* ssh_get_authentication_socket().
*/
void
ssh_close_authentication_socket(int sock)
{
if (getenv(SSH_AUTHSOCKET_ENV_NAME))
close(sock);
}
/* Lock/unlock agent */
int
ssh_lock_agent(int sock, int lock, const char *password)
{
int r;
u_char type = lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK;
struct sshbuf *msg;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshbuf_put_cstring(msg, password)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
static int
deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp)
{
int r;
char *comment = NULL;
const u_char *blob;
size_t blen;
if ((r = sshbuf_get_string_direct(ids, &blob, &blen)) != 0 ||
(r = sshbuf_get_cstring(ids, &comment, NULL)) != 0)
goto out;
if ((r = sshkey_from_blob(blob, blen, keyp)) != 0)
goto out;
if (commentp != NULL) {
*commentp = comment;
comment = NULL;
}
r = 0;
out:
free(comment);
return r;
}
/*
* Fetch list of identities held by the agent.
*/
int
ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp)
{
u_char type;
u_int32_t num, i;
struct sshbuf *msg;
struct ssh_identitylist *idl = NULL;
int r;
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
/* Get message type, and verify that we got a proper answer. */
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
if (agent_failed(type)) {
r = SSH_ERR_AGENT_FAILURE;
goto out;
} else if (type != SSH2_AGENT_IDENTITIES_ANSWER) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* Get the number of entries in the response and check it for sanity. */
if ((r = sshbuf_get_u32(msg, &num)) != 0)
goto out;
if (num > MAX_AGENT_IDENTITIES) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (num == 0) {
r = SSH_ERR_AGENT_NO_IDENTITIES;
goto out;
}
/* Deserialise the response into a list of keys/comments */
if ((idl = calloc(1, sizeof(*idl))) == NULL ||
(idl->keys = calloc(num, sizeof(*idl->keys))) == NULL ||
(idl->comments = calloc(num, sizeof(*idl->comments))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
for (i = 0; i < num;) {
if ((r = deserialise_identity2(msg, &(idl->keys[i]),
&(idl->comments[i]))) != 0) {
if (r == SSH_ERR_KEY_TYPE_UNKNOWN) {
/* Gracefully skip unknown key types */
num--;
continue;
} else
goto out;
}
i++;
}
idl->nkeys = num;
*idlp = idl;
idl = NULL;
r = 0;
out:
sshbuf_free(msg);
if (idl != NULL)
ssh_free_identitylist(idl);
return r;
}
void
ssh_free_identitylist(struct ssh_identitylist *idl)
{
size_t i;
if (idl == NULL)
return;
for (i = 0; i < idl->nkeys; i++) {
if (idl->keys != NULL)
sshkey_free(idl->keys[i]);
if (idl->comments != NULL)
free(idl->comments[i]);
}
free(idl);
}
/*
* Sends a challenge (typically from a server via ssh(1)) to the agent,
* and waits for a response from the agent.
* Returns true (non-zero) if the agent gave the correct answer, zero
* otherwise.
*/
/* encode signature algorithm in flag bits, so we can keep the msg format */
static u_int
agent_encode_alg(const struct sshkey *key, const char *alg)
{
- if (alg != NULL && key->type == KEY_RSA) {
- if (strcmp(alg, "rsa-sha2-256") == 0)
+ if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) {
+ if (strcmp(alg, "rsa-sha2-256") == 0 ||
+ strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
return SSH_AGENT_RSA_SHA2_256;
- else if (strcmp(alg, "rsa-sha2-512") == 0)
+ if (strcmp(alg, "rsa-sha2-512") == 0 ||
+ strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
return SSH_AGENT_RSA_SHA2_512;
}
return 0;
}
/* ask agent to sign data, returns err.h code on error, 0 on success */
int
ssh_agent_sign(int sock, const struct sshkey *key,
u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *alg, u_int compat)
{
struct sshbuf *msg;
u_char *sig = NULL, type = 0;
size_t len = 0;
u_int flags = 0;
int r = SSH_ERR_INTERNAL_ERROR;
*sigp = NULL;
*lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
flags |= agent_encode_alg(key, alg);
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
(r = sshkey_puts(key, msg)) != 0 ||
(r = sshbuf_put_string(msg, data, datalen)) != 0 ||
(r = sshbuf_put_u32(msg, flags)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
if (agent_failed(type)) {
r = SSH_ERR_AGENT_FAILURE;
goto out;
} else if (type != SSH2_AGENT_SIGN_RESPONSE) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((r = sshbuf_get_string(msg, &sig, &len)) != 0)
goto out;
/* Check what we actually got back from the agent. */
if ((r = sshkey_check_sigtype(sig, len, alg)) != 0)
goto out;
/* success */
*sigp = sig;
*lenp = len;
sig = NULL;
len = 0;
r = 0;
out:
freezero(sig, len);
sshbuf_free(msg);
return r;
}
/* Encode key for a message to the agent. */
static int
encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign)
{
int r;
if (life != 0) {
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 ||
(r = sshbuf_put_u32(m, life)) != 0)
goto out;
}
if (confirm != 0) {
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0)
goto out;
}
if (maxsign != 0) {
if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_MAXSIGN)) != 0 ||
(r = sshbuf_put_u32(m, maxsign)) != 0)
goto out;
}
r = 0;
out:
return r;
}
/*
* Adds an identity to the authentication server.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_add_identity_constrained(int sock, const struct sshkey *key,
const char *comment, u_int life, u_int confirm, u_int maxsign)
{
struct sshbuf *msg;
int r, constrained = (life || confirm || maxsign);
u_char type;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_RSA_CERT:
case KEY_DSA:
case KEY_DSA_CERT:
case KEY_ECDSA:
case KEY_ECDSA_CERT:
#endif
case KEY_ED25519:
case KEY_ED25519_CERT:
case KEY_XMSS:
case KEY_XMSS_CERT:
type = constrained ?
SSH2_AGENTC_ADD_ID_CONSTRAINED :
SSH2_AGENTC_ADD_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshkey_private_serialize_maxsign(key, msg, maxsign,
NULL)) != 0 ||
(r = sshbuf_put_cstring(msg, comment)) != 0)
goto out;
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if (constrained &&
(r = encode_constraints(msg, life, confirm, maxsign)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
/*
* Removes an identity from the authentication server.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_remove_identity(int sock, struct sshkey *key)
{
struct sshbuf *msg;
int r;
u_char type, *blob = NULL;
size_t blen;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if (key->type != KEY_UNSPEC) {
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0)
goto out;
if ((r = sshbuf_put_u8(msg,
SSH2_AGENTC_REMOVE_IDENTITY)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0)
goto out;
} else {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
if (blob != NULL) {
explicit_bzero(blob, blen);
free(blob);
}
sshbuf_free(msg);
return r;
}
/*
* Add/remove an token-based identity from the authentication server.
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
u_int life, u_int confirm)
{
struct sshbuf *msg;
int r, constrained = (life || confirm);
u_char type;
if (add) {
type = constrained ?
SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED :
SSH_AGENTC_ADD_SMARTCARD_KEY;
} else
type = SSH_AGENTC_REMOVE_SMARTCARD_KEY;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshbuf_put_cstring(msg, reader_id)) != 0 ||
(r = sshbuf_put_cstring(msg, pin)) != 0)
goto out;
if (constrained &&
(r = encode_constraints(msg, life, confirm, 0)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
/*
* Removes all identities from the agent.
* This call is intended only for use by ssh-add(1) and like applications.
*
* This supports the SSH protocol 1 message to because, when clearing all
* keys from an agent, we generally want to clear both protocol v1 and v2
* keys.
*/
int
ssh_remove_all_identities(int sock, int version)
{
struct sshbuf *msg;
u_char type = (version == 1) ?
SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
int r;
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0)
goto out;
if ((r = ssh_request_reply(sock, msg, msg)) != 0)
goto out;
if ((r = sshbuf_get_u8(msg, &type)) != 0)
goto out;
r = decode_reply(type);
out:
sshbuf_free(msg);
return r;
}
diff --git a/channels.c b/channels.c
index c85d46abd762..657381b8037d 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4876 +1,4885 @@
-/* $OpenBSD: channels.c,v 1.386 2018/10/04 01:04:52 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.389 2019/01/19 21:37:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file contains functions for generic socket connection forwarding.
* There is also code for initiating connection forwarding for X11 connections,
* arbitrary tcp/ip connections, and the authentication agent connection.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 support added by Markus Friedl.
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 1999 Dug Song. All rights reserved.
* Copyright (c) 1999 Theo de Raadt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#include <stdarg.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "packet.h"
#include "log.h"
#include "misc.h"
#include "channels.h"
#include "compat.h"
#include "canohost.h"
#include "sshkey.h"
#include "authfd.h"
#include "pathnames.h"
#include "match.h"
/* -- agent forwarding */
#define NUM_SOCKS 10
/* -- tcp forwarding */
/* special-case port number meaning allow any port */
#define FWD_PERMIT_ANY_PORT 0
/* special-case wildcard meaning allow any host */
#define FWD_PERMIT_ANY_HOST "*"
/* -- X11 forwarding */
/* Maximum number of fake X11 displays to try. */
#define MAX_DISPLAYS 1000
/* Per-channel callback for pre/post select() actions */
typedef void chan_fn(struct ssh *, Channel *c,
fd_set *readset, fd_set *writeset);
/*
* Data structure for storing which hosts are permitted for forward requests.
* The local sides of any remote forwards are stored in this array to prevent
* a corrupt remote server from accessing arbitrary TCP/IP ports on our local
* network (which might be behind a firewall).
*/
/* XXX: streamlocal wants a path instead of host:port */
/* Overload host_to_connect; we could just make this match Forward */
/* XXX - can we use listen_host instead of listen_path? */
struct permission {
char *host_to_connect; /* Connect to 'host'. */
int port_to_connect; /* Connect to 'port'. */
char *listen_host; /* Remote side should listen address. */
char *listen_path; /* Remote side should listen path. */
int listen_port; /* Remote side should listen port. */
Channel *downstream; /* Downstream mux*/
};
/*
* Stores the forwarding permission state for a single direction (local or
* remote).
*/
struct permission_set {
/*
* List of all local permitted host/port pairs to allow for the
* user.
*/
u_int num_permitted_user;
struct permission *permitted_user;
/*
* List of all permitted host/port pairs to allow for the admin.
*/
u_int num_permitted_admin;
struct permission *permitted_admin;
/*
* If this is true, all opens/listens are permitted. This is the
* case on the server on which we have to trust the client anyway,
* and the user could do anything after logging in.
*/
int all_permitted;
};
/* Master structure for channels state */
struct ssh_channels {
/*
* Pointer to an array containing all allocated channels. The array
* is dynamically extended as needed.
*/
Channel **channels;
/*
* Size of the channel array. All slots of the array must always be
* initialized (at least the type field); unused slots set to NULL
*/
u_int channels_alloc;
/*
* Maximum file descriptor value used in any of the channels. This is
* updated in channel_new.
*/
int channel_max_fd;
/*
* 'channel_pre*' are called just before select() to add any bits
* relevant to channels in the select bitmasks.
*
* 'channel_post*': perform any appropriate operations for
* channels which have events pending.
*/
chan_fn **channel_pre;
chan_fn **channel_post;
/* -- tcp forwarding */
struct permission_set local_perms;
struct permission_set remote_perms;
/* -- X11 forwarding */
/* Saved X11 local (client) display. */
char *x11_saved_display;
/* Saved X11 authentication protocol name. */
char *x11_saved_proto;
/* Saved X11 authentication data. This is the real data. */
char *x11_saved_data;
u_int x11_saved_data_len;
/* Deadline after which all X11 connections are refused */
u_int x11_refuse_time;
/*
* Fake X11 authentication data. This is what the server will be
* sending us; we should replace any occurrences of this by the
* real data.
*/
u_char *x11_fake_data;
u_int x11_fake_data_len;
/* AF_UNSPEC or AF_INET or AF_INET6 */
int IPv4or6;
};
/* helper */
static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype);
static const char *channel_rfwd_bind_host(const char *listen_host);
/* non-blocking connect helpers */
static int connect_next(struct channel_connect *);
static void channel_connect_ctx_free(struct channel_connect *);
static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *);
static int rdynamic_connect_finish(struct ssh *, Channel *);
/* Setup helper */
static void channel_handler_init(struct ssh_channels *sc);
/* -- channel core */
void
channel_init_channels(struct ssh *ssh)
{
struct ssh_channels *sc;
- if ((sc = calloc(1, sizeof(*sc))) == NULL ||
- (sc->channel_pre = calloc(SSH_CHANNEL_MAX_TYPE,
- sizeof(*sc->channel_pre))) == NULL ||
- (sc->channel_post = calloc(SSH_CHANNEL_MAX_TYPE,
- sizeof(*sc->channel_post))) == NULL)
+ if ((sc = calloc(1, sizeof(*sc))) == NULL)
fatal("%s: allocation failed", __func__);
sc->channels_alloc = 10;
sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels));
sc->IPv4or6 = AF_UNSPEC;
channel_handler_init(sc);
ssh->chanctxt = sc;
}
Channel *
channel_by_id(struct ssh *ssh, int id)
{
Channel *c;
if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) {
logit("%s: %d: bad id", __func__, id);
return NULL;
}
c = ssh->chanctxt->channels[id];
if (c == NULL) {
logit("%s: %d: bad id: channel free", __func__, id);
return NULL;
}
return c;
}
Channel *
channel_by_remote_id(struct ssh *ssh, u_int remote_id)
{
Channel *c;
u_int i;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c != NULL && c->have_remote_id && c->remote_id == remote_id)
return c;
}
return NULL;
}
/*
* Returns the channel if it is allowed to receive protocol messages.
* Private channels, like listening sockets, may not receive messages.
*/
Channel *
channel_lookup(struct ssh *ssh, int id)
{
Channel *c;
if ((c = channel_by_id(ssh, id)) == NULL)
return NULL;
switch (c->type) {
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_DYNAMIC:
case SSH_CHANNEL_RDYNAMIC_OPEN:
case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_MUX_PROXY:
return c;
}
logit("Non-public channel %d, type %d.", id, c->type);
return NULL;
}
/*
* Register filedescriptors for a channel, used when allocating a channel or
* when the channel consumer/producer is ready, e.g. shell exec'd
*/
static void
channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
int extusage, int nonblock, int is_tty)
{
struct ssh_channels *sc = ssh->chanctxt;
/* Update the maximum file descriptor value. */
sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd);
sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd);
sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd);
if (rfd != -1)
fcntl(rfd, F_SETFD, FD_CLOEXEC);
if (wfd != -1 && wfd != rfd)
fcntl(wfd, F_SETFD, FD_CLOEXEC);
if (efd != -1 && efd != rfd && efd != wfd)
fcntl(efd, F_SETFD, FD_CLOEXEC);
c->rfd = rfd;
c->wfd = wfd;
c->sock = (rfd == wfd) ? rfd : -1;
c->efd = efd;
c->extended_usage = extusage;
if ((c->isatty = is_tty) != 0)
debug2("channel %d: rfd %d isatty", c->self, c->rfd);
#ifdef _AIX
/* XXX: Later AIX versions can't push as much data to tty */
c->wfd_isatty = is_tty || isatty(c->wfd);
#endif
/* enable nonblocking mode */
if (nonblock) {
if (rfd != -1)
set_nonblock(rfd);
if (wfd != -1)
set_nonblock(wfd);
if (efd != -1)
set_nonblock(efd);
}
}
/*
* Allocate a new channel object and set its type and socket. This will cause
* remote_name to be freed.
*/
Channel *
channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
{
struct ssh_channels *sc = ssh->chanctxt;
u_int i, found;
Channel *c;
/* Try to find a free slot where to put the new channel. */
for (i = 0; i < sc->channels_alloc; i++) {
if (sc->channels[i] == NULL) {
/* Found a free slot. */
found = i;
break;
}
}
if (i >= sc->channels_alloc) {
/*
* There are no free slots. Take last+1 slot and expand
* the array.
*/
found = sc->channels_alloc;
if (sc->channels_alloc > CHANNELS_MAX_CHANNELS)
fatal("%s: internal error: channels_alloc %d too big",
__func__, sc->channels_alloc);
sc->channels = xrecallocarray(sc->channels, sc->channels_alloc,
sc->channels_alloc + 10, sizeof(*sc->channels));
sc->channels_alloc += 10;
debug2("channel: expanding %d", sc->channels_alloc);
}
/* Initialize and return new channel. */
c = sc->channels[found] = xcalloc(1, sizeof(Channel));
if ((c->input = sshbuf_new()) == NULL ||
(c->output = sshbuf_new()) == NULL ||
(c->extended = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
c->ostate = CHAN_OUTPUT_OPEN;
c->istate = CHAN_INPUT_OPEN;
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
c->self = found;
c->type = type;
c->ctype = ctype;
c->local_window = window;
c->local_window_max = window;
c->local_maxpacket = maxpack;
c->remote_name = xstrdup(remote_name);
c->ctl_chan = -1;
c->delayed = 1; /* prevent call to channel_post handler */
TAILQ_INIT(&c->status_confirms);
debug("channel %d: new [%s]", found, remote_name);
return c;
}
static void
channel_find_maxfd(struct ssh_channels *sc)
{
u_int i;
int max = 0;
Channel *c;
for (i = 0; i < sc->channels_alloc; i++) {
c = sc->channels[i];
if (c != NULL) {
max = MAXIMUM(max, c->rfd);
max = MAXIMUM(max, c->wfd);
max = MAXIMUM(max, c->efd);
}
}
sc->channel_max_fd = max;
}
int
channel_close_fd(struct ssh *ssh, int *fdp)
{
struct ssh_channels *sc = ssh->chanctxt;
int ret = 0, fd = *fdp;
if (fd != -1) {
ret = close(fd);
*fdp = -1;
if (fd == sc->channel_max_fd)
channel_find_maxfd(sc);
}
return ret;
}
/* Close all channel fd/socket. */
static void
channel_close_fds(struct ssh *ssh, Channel *c)
{
int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
channel_close_fd(ssh, &c->sock);
if (rfd != sock)
channel_close_fd(ssh, &c->rfd);
if (wfd != sock && wfd != rfd)
channel_close_fd(ssh, &c->wfd);
if (efd != sock && efd != rfd && efd != wfd)
channel_close_fd(ssh, &c->efd);
}
static void
fwd_perm_clear(struct permission *perm)
{
free(perm->host_to_connect);
free(perm->listen_host);
free(perm->listen_path);
bzero(perm, sizeof(*perm));
}
/* Returns an printable name for the specified forwarding permission list */
static const char *
fwd_ident(int who, int where)
{
if (who == FORWARD_ADM) {
if (where == FORWARD_LOCAL)
return "admin local";
else if (where == FORWARD_REMOTE)
return "admin remote";
} else if (who == FORWARD_USER) {
if (where == FORWARD_LOCAL)
return "user local";
else if (where == FORWARD_REMOTE)
return "user remote";
}
fatal("Unknown forward permission list %d/%d", who, where);
}
/* Returns the forwarding permission list for the specified direction */
static struct permission_set *
permission_set_get(struct ssh *ssh, int where)
{
struct ssh_channels *sc = ssh->chanctxt;
switch (where) {
case FORWARD_LOCAL:
return &sc->local_perms;
break;
case FORWARD_REMOTE:
return &sc->remote_perms;
break;
default:
fatal("%s: invalid forwarding direction %d", __func__, where);
}
}
/* Reutrns pointers to the specified forwarding list and its element count */
static void
permission_set_get_array(struct ssh *ssh, int who, int where,
struct permission ***permpp, u_int **npermpp)
{
struct permission_set *pset = permission_set_get(ssh, where);
switch (who) {
case FORWARD_USER:
*permpp = &pset->permitted_user;
*npermpp = &pset->num_permitted_user;
break;
case FORWARD_ADM:
*permpp = &pset->permitted_admin;
*npermpp = &pset->num_permitted_admin;
break;
default:
fatal("%s: invalid forwarding client %d", __func__, who);
}
}
/* Adds an entry to the spcified forwarding list */
static int
permission_set_add(struct ssh *ssh, int who, int where,
const char *host_to_connect, int port_to_connect,
const char *listen_host, const char *listen_path, int listen_port,
Channel *downstream)
{
struct permission **permp;
u_int n, *npermp;
permission_set_get_array(ssh, who, where, &permp, &npermp);
if (*npermp >= INT_MAX)
fatal("%s: %s overflow", __func__, fwd_ident(who, where));
*permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp));
n = (*npermp)++;
#define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s))
(*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect);
(*permp)[n].port_to_connect = port_to_connect;
(*permp)[n].listen_host = MAYBE_DUP(listen_host);
(*permp)[n].listen_path = MAYBE_DUP(listen_path);
(*permp)[n].listen_port = listen_port;
(*permp)[n].downstream = downstream;
#undef MAYBE_DUP
return (int)n;
}
static void
mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
struct permission *perm;
int r;
u_int i;
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (perm->downstream != c)
continue;
/* cancel on the server, since mux client is gone */
debug("channel %d: cleanup remote forward for %s:%u",
c->self, perm->listen_host, perm->listen_port);
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh,
"cancel-tcpip-forward")) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 ||
(r = sshpkt_put_cstring(ssh,
channel_rfwd_bind_host(perm->listen_host))) != 0 ||
(r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
fatal("%s: channel %i: %s", __func__,
c->self, ssh_err(r));
}
fwd_perm_clear(perm); /* unregister */
}
}
/* Free the channel and close its fd/socket. */
void
channel_free(struct ssh *ssh, Channel *c)
{
struct ssh_channels *sc = ssh->chanctxt;
char *s;
u_int i, n;
Channel *other;
struct channel_confirm *cc;
for (n = 0, i = 0; i < sc->channels_alloc; i++) {
if ((other = sc->channels[i]) == NULL)
continue;
n++;
/* detach from mux client and prepare for closing */
if (c->type == SSH_CHANNEL_MUX_CLIENT &&
other->type == SSH_CHANNEL_MUX_PROXY &&
other->mux_ctx == c) {
other->mux_ctx = NULL;
other->type = SSH_CHANNEL_OPEN;
other->istate = CHAN_INPUT_CLOSED;
other->ostate = CHAN_OUTPUT_CLOSED;
}
}
debug("channel %d: free: %s, nchannels %u", c->self,
c->remote_name ? c->remote_name : "???", n);
if (c->type == SSH_CHANNEL_MUX_CLIENT)
mux_remove_remote_forwardings(ssh, c);
if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) {
s = channel_open_message(ssh);
debug3("channel %d: status: %s", c->self, s);
free(s);
}
channel_close_fds(ssh, c);
sshbuf_free(c->input);
sshbuf_free(c->output);
sshbuf_free(c->extended);
c->input = c->output = c->extended = NULL;
free(c->remote_name);
c->remote_name = NULL;
free(c->path);
c->path = NULL;
free(c->listening_addr);
c->listening_addr = NULL;
while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
if (cc->abandon_cb != NULL)
cc->abandon_cb(ssh, c, cc->ctx);
TAILQ_REMOVE(&c->status_confirms, cc, entry);
explicit_bzero(cc, sizeof(*cc));
free(cc);
}
if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
c->filter_cleanup(ssh, c->self, c->filter_ctx);
sc->channels[c->self] = NULL;
explicit_bzero(c, sizeof(*c));
free(c);
}
void
channel_free_all(struct ssh *ssh)
{
u_int i;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++)
if (ssh->chanctxt->channels[i] != NULL)
channel_free(ssh, ssh->chanctxt->channels[i]);
}
/*
* Closes the sockets/fds of all channels. This is used to close extra file
* descriptors after a fork.
*/
void
channel_close_all(struct ssh *ssh)
{
u_int i;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++)
if (ssh->chanctxt->channels[i] != NULL)
channel_close_fds(ssh, ssh->chanctxt->channels[i]);
}
/*
* Stop listening to channels.
*/
void
channel_stop_listening(struct ssh *ssh)
{
u_int i;
Channel *c;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c != NULL) {
switch (c->type) {
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
channel_close_fd(ssh, &c->sock);
channel_free(ssh, c);
break;
}
}
}
}
/*
* Returns true if no channel has too much buffered data, and false if one or
* more channel is overfull.
*/
int
channel_not_very_much_buffered_data(struct ssh *ssh)
{
u_int i;
u_int maxsize = ssh_packet_get_maxsize(ssh);
Channel *c;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_OPEN)
continue;
if (sshbuf_len(c->output) > maxsize) {
debug2("channel %d: big output buffer %zu > %u",
c->self, sshbuf_len(c->output), maxsize);
return 0;
}
}
return 1;
}
/* Returns true if any channel is still open. */
int
channel_still_open(struct ssh *ssh)
{
u_int i;
Channel *c;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c == NULL)
continue;
switch (c->type) {
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_DYNAMIC:
case SSH_CHANNEL_RDYNAMIC_OPEN:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
continue;
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_MUX_CLIENT:
case SSH_CHANNEL_MUX_PROXY:
return 1;
default:
fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
return 0;
}
/* Returns the id of an open channel suitable for keepaliving */
int
channel_find_open(struct ssh *ssh)
{
u_int i;
Channel *c;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c == NULL || !c->have_remote_id)
continue;
switch (c->type) {
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_DYNAMIC:
case SSH_CHANNEL_RDYNAMIC_OPEN:
case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_MUX_CLIENT:
case SSH_CHANNEL_MUX_PROXY:
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_X11_OPEN:
return i;
default:
fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
return -1;
}
/* Returns the state of the channel's extended usage flag */
const char *
channel_format_extended_usage(const Channel *c)
{
if (c->efd == -1)
return "closed";
switch (c->extended_usage) {
case CHAN_EXTENDED_WRITE:
return "write";
case CHAN_EXTENDED_READ:
return "read";
case CHAN_EXTENDED_IGNORE:
return "ignore";
default:
return "UNKNOWN";
}
}
static char *
channel_format_status(const Channel *c)
{
char *ret = NULL;
xasprintf(&ret, "t%d %s%u i%u/%zu o%u/%zu e[%s]/%zu "
"fd %d/%d/%d sock %d cc %d",
c->type,
c->have_remote_id ? "r" : "nr", c->remote_id,
c->istate, sshbuf_len(c->input),
c->ostate, sshbuf_len(c->output),
channel_format_extended_usage(c), sshbuf_len(c->extended),
c->rfd, c->wfd, c->efd, c->sock, c->ctl_chan);
return ret;
}
/*
* Returns a message describing the currently open forwarded connections,
* suitable for sending to the client. The message contains crlf pairs for
* newlines.
*/
char *
channel_open_message(struct ssh *ssh)
{
struct sshbuf *buf;
Channel *c;
u_int i;
int r;
char *cp, *ret;
if ((buf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_putf(buf,
"The following connections are open:\r\n")) != 0)
fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c == NULL)
continue;
switch (c->type) {
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_PORT_LISTENER:
case SSH_CHANNEL_RPORT_LISTENER:
case SSH_CHANNEL_CLOSED:
case SSH_CHANNEL_AUTH_SOCKET:
case SSH_CHANNEL_ZOMBIE:
case SSH_CHANNEL_ABANDONED:
case SSH_CHANNEL_MUX_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
continue;
case SSH_CHANNEL_LARVAL:
case SSH_CHANNEL_OPENING:
case SSH_CHANNEL_CONNECTING:
case SSH_CHANNEL_DYNAMIC:
case SSH_CHANNEL_RDYNAMIC_OPEN:
case SSH_CHANNEL_RDYNAMIC_FINISH:
case SSH_CHANNEL_OPEN:
case SSH_CHANNEL_X11_OPEN:
case SSH_CHANNEL_MUX_PROXY:
case SSH_CHANNEL_MUX_CLIENT:
cp = channel_format_status(c);
if ((r = sshbuf_putf(buf, " #%d %.300s (%s)\r\n",
c->self, c->remote_name, cp)) != 0) {
free(cp);
fatal("%s: sshbuf_putf: %s",
__func__, ssh_err(r));
}
free(cp);
continue;
default:
fatal("%s: bad channel type %d", __func__, c->type);
/* NOTREACHED */
}
}
if ((ret = sshbuf_dup_string(buf)) == NULL)
fatal("%s: sshbuf_dup_string", __func__);
sshbuf_free(buf);
return ret;
}
static void
open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type)
{
int r;
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
(r = sshpkt_put_cstring(ssh, type)) != 0 ||
(r = sshpkt_put_u32(ssh, c->self)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r));
}
}
void
channel_send_open(struct ssh *ssh, int id)
{
Channel *c = channel_lookup(ssh, id);
int r;
if (c == NULL) {
logit("channel_send_open: %d: bad id", id);
return;
}
debug2("channel %d: send open", id);
open_preamble(ssh, __func__, c, c->ctype);
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
}
void
channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm)
{
Channel *c = channel_lookup(ssh, id);
int r;
if (c == NULL) {
logit("%s: %d: unknown channel id", __func__, id);
return;
}
if (!c->have_remote_id)
fatal(":%s: channel %d: no remote id", __func__, c->self);
debug2("channel %d: request %s confirm %d", id, service, wantconfirm);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_cstring(ssh, service)) != 0 ||
(r = sshpkt_put_u8(ssh, wantconfirm)) != 0) {
fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
}
}
void
channel_register_status_confirm(struct ssh *ssh, int id,
channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx)
{
struct channel_confirm *cc;
Channel *c;
if ((c = channel_lookup(ssh, id)) == NULL)
fatal("%s: %d: bad id", __func__, id);
cc = xcalloc(1, sizeof(*cc));
cc->cb = cb;
cc->abandon_cb = abandon_cb;
cc->ctx = ctx;
TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry);
}
void
channel_register_open_confirm(struct ssh *ssh, int id,
channel_open_fn *fn, void *ctx)
{
Channel *c = channel_lookup(ssh, id);
if (c == NULL) {
logit("%s: %d: bad id", __func__, id);
return;
}
c->open_confirm = fn;
c->open_confirm_ctx = ctx;
}
void
channel_register_cleanup(struct ssh *ssh, int id,
channel_callback_fn *fn, int do_close)
{
Channel *c = channel_by_id(ssh, id);
if (c == NULL) {
logit("%s: %d: bad id", __func__, id);
return;
}
c->detach_user = fn;
c->detach_close = do_close;
}
void
channel_cancel_cleanup(struct ssh *ssh, int id)
{
Channel *c = channel_by_id(ssh, id);
if (c == NULL) {
logit("%s: %d: bad id", __func__, id);
return;
}
c->detach_user = NULL;
c->detach_close = 0;
}
void
channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn,
channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
{
Channel *c = channel_lookup(ssh, id);
if (c == NULL) {
logit("%s: %d: bad id", __func__, id);
return;
}
c->input_filter = ifn;
c->output_filter = ofn;
c->filter_ctx = ctx;
c->filter_cleanup = cfn;
}
void
channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd,
int extusage, int nonblock, int is_tty, u_int window_max)
{
Channel *c = channel_lookup(ssh, id);
int r;
if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
fatal("channel_activate for non-larval channel %d.", id);
if (!c->have_remote_id)
fatal(":%s: channel %d: no remote id", __func__, c->self);
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty);
c->type = SSH_CHANNEL_OPEN;
c->local_window = c->local_window_max = window_max;
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
}
static void
channel_pre_listener(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
FD_SET(c->sock, readset);
}
static void
channel_pre_connecting(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
debug3("channel %d: waiting for connection", c->self);
FD_SET(c->sock, writeset);
}
static void
channel_pre_open(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
if (c->istate == CHAN_INPUT_OPEN &&
c->remote_window > 0 &&
sshbuf_len(c->input) < c->remote_window &&
sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)
FD_SET(c->rfd, readset);
if (c->ostate == CHAN_OUTPUT_OPEN ||
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
if (sshbuf_len(c->output) > 0) {
FD_SET(c->wfd, writeset);
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
debug2("channel %d: "
"obuf_empty delayed efd %d/(%zu)", c->self,
c->efd, sshbuf_len(c->extended));
else
chan_obuf_empty(ssh, c);
}
}
/** XXX check close conditions, too */
if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED &&
c->ostate == CHAN_OUTPUT_CLOSED)) {
if (c->extended_usage == CHAN_EXTENDED_WRITE &&
sshbuf_len(c->extended) > 0)
FD_SET(c->efd, writeset);
else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&
(c->extended_usage == CHAN_EXTENDED_READ ||
c->extended_usage == CHAN_EXTENDED_IGNORE) &&
sshbuf_len(c->extended) < c->remote_window)
FD_SET(c->efd, readset);
}
/* XXX: What about efd? races? */
}
/*
* This is a special state for X11 authentication spoofing. An opened X11
* connection (when authentication spoofing is being done) remains in this
* state until the first packet has been completely read. The authentication
* data in that packet is then substituted by the real data if it matches the
* fake data, and the channel is put into normal mode.
* XXX All this happens at the client side.
* Returns: 0 = need more data, -1 = wrong cookie, 1 = ok
*/
static int
x11_open_helper(struct ssh *ssh, struct sshbuf *b)
{
struct ssh_channels *sc = ssh->chanctxt;
u_char *ucp;
u_int proto_len, data_len;
/* Is this being called after the refusal deadline? */
if (sc->x11_refuse_time != 0 &&
(u_int)monotime() >= sc->x11_refuse_time) {
verbose("Rejected X11 connection after ForwardX11Timeout "
"expired");
return -1;
}
/* Check if the fixed size part of the packet is in buffer. */
if (sshbuf_len(b) < 12)
return 0;
/* Parse the lengths of variable-length fields. */
ucp = sshbuf_mutable_ptr(b);
if (ucp[0] == 0x42) { /* Byte order MSB first. */
proto_len = 256 * ucp[6] + ucp[7];
data_len = 256 * ucp[8] + ucp[9];
} else if (ucp[0] == 0x6c) { /* Byte order LSB first. */
proto_len = ucp[6] + 256 * ucp[7];
data_len = ucp[8] + 256 * ucp[9];
} else {
debug2("Initial X11 packet contains bad byte order byte: 0x%x",
ucp[0]);
return -1;
}
/* Check if the whole packet is in buffer. */
if (sshbuf_len(b) <
12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
return 0;
/* Check if authentication protocol matches. */
if (proto_len != strlen(sc->x11_saved_proto) ||
memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) {
debug2("X11 connection uses different authentication protocol.");
return -1;
}
/* Check if authentication data matches our fake data. */
if (data_len != sc->x11_fake_data_len ||
timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3),
sc->x11_fake_data, sc->x11_fake_data_len) != 0) {
debug2("X11 auth data does not match fake data.");
return -1;
}
/* Check fake data length */
if (sc->x11_fake_data_len != sc->x11_saved_data_len) {
error("X11 fake_data_len %d != saved_data_len %d",
sc->x11_fake_data_len, sc->x11_saved_data_len);
return -1;
}
/*
* Received authentication protocol and data match
* our fake data. Substitute the fake data with real
* data.
*/
memcpy(ucp + 12 + ((proto_len + 3) & ~3),
sc->x11_saved_data, sc->x11_saved_data_len);
return 1;
}
static void
channel_pre_x11_open(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
int ret = x11_open_helper(ssh, c->output);
/* c->force_drain = 1; */
if (ret == 1) {
c->type = SSH_CHANNEL_OPEN;
channel_pre_open(ssh, c, readset, writeset);
} else if (ret == -1) {
logit("X11 connection rejected because of wrong authentication.");
debug2("X11 rejected %d i%d/o%d",
c->self, c->istate, c->ostate);
chan_read_failed(ssh, c);
sshbuf_reset(c->input);
chan_ibuf_empty(ssh, c);
sshbuf_reset(c->output);
chan_write_failed(ssh, c);
debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate);
}
}
static void
channel_pre_mux_client(struct ssh *ssh,
Channel *c, fd_set *readset, fd_set *writeset)
{
if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&
sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)
FD_SET(c->rfd, readset);
if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
/* clear buffer immediately (discard any partial packet) */
sshbuf_reset(c->input);
chan_ibuf_empty(ssh, c);
/* Start output drain. XXX just kill chan? */
chan_rcvd_oclose(ssh, c);
}
if (c->ostate == CHAN_OUTPUT_OPEN ||
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
if (sshbuf_len(c->output) > 0)
FD_SET(c->wfd, writeset);
else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)
chan_obuf_empty(ssh, c);
}
}
/* try to decode a socks4 header */
static int
channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
{
const u_char *p;
char *host;
u_int len, have, i, found, need;
char username[256];
struct {
u_int8_t version;
u_int8_t command;
u_int16_t dest_port;
struct in_addr dest_addr;
} s4_req, s4_rsp;
int r;
debug2("channel %d: decode socks4", c->self);
have = sshbuf_len(input);
len = sizeof(s4_req);
if (have < len)
return 0;
p = sshbuf_ptr(input);
need = 1;
/* SOCKS4A uses an invalid IP address 0.0.0.x */
if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) {
debug2("channel %d: socks4a request", c->self);
/* ... and needs an extra string (the hostname) */
need = 2;
}
/* Check for terminating NUL on the string(s) */
for (found = 0, i = len; i < have; i++) {
if (p[i] == '\0') {
found++;
if (found == need)
break;
}
if (i > 1024) {
/* the peer is probably sending garbage */
debug("channel %d: decode socks4: too long",
c->self);
return -1;
}
}
if (found < need)
return 0;
if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 ||
(r = sshbuf_get(input, &s4_req.command, 1)) != 0 ||
(r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 ||
(r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) {
debug("channels %d: decode socks4: %s", c->self, ssh_err(r));
return -1;
}
have = sshbuf_len(input);
p = sshbuf_ptr(input);
if (memchr(p, '\0', have) == NULL) {
error("channel %d: decode socks4: user not nul terminated",
c->self);
return -1;
}
len = strlen(p);
debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
len++; /* trailing '\0' */
strlcpy(username, p, sizeof(username));
if ((r = sshbuf_consume(input, len)) != 0) {
fatal("%s: channel %d: consume: %s", __func__,
c->self, ssh_err(r));
}
free(c->path);
c->path = NULL;
if (need == 1) { /* SOCKS4: one string */
host = inet_ntoa(s4_req.dest_addr);
c->path = xstrdup(host);
} else { /* SOCKS4A: two strings */
have = sshbuf_len(input);
p = sshbuf_ptr(input);
if (memchr(p, '\0', have) == NULL) {
error("channel %d: decode socks4a: host not nul "
"terminated", c->self);
return -1;
}
len = strlen(p);
debug2("channel %d: decode socks4a: host %s/%d",
c->self, p, len);
len++; /* trailing '\0' */
if (len > NI_MAXHOST) {
error("channel %d: hostname \"%.100s\" too long",
c->self, p);
return -1;
}
c->path = xstrdup(p);
if ((r = sshbuf_consume(input, len)) != 0) {
fatal("%s: channel %d: consume: %s", __func__,
c->self, ssh_err(r));
}
}
c->host_port = ntohs(s4_req.dest_port);
debug2("channel %d: dynamic request: socks4 host %s port %u command %u",
c->self, c->path, c->host_port, s4_req.command);
if (s4_req.command != 1) {
debug("channel %d: cannot handle: %s cn %d",
c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command);
return -1;
}
s4_rsp.version = 0; /* vn: 0 for reply */
s4_rsp.command = 90; /* cd: req granted */
s4_rsp.dest_port = 0; /* ignored */
s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) {
fatal("%s: channel %d: append reply: %s", __func__,
c->self, ssh_err(r));
}
return 1;
}
/* try to decode a socks5 header */
#define SSH_SOCKS5_AUTHDONE 0x1000
#define SSH_SOCKS5_NOAUTH 0x00
#define SSH_SOCKS5_IPV4 0x01
#define SSH_SOCKS5_DOMAIN 0x03
#define SSH_SOCKS5_IPV6 0x04
#define SSH_SOCKS5_CONNECT 0x01
#define SSH_SOCKS5_SUCCESS 0x00
static int
channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
{
/* XXX use get/put_u8 instead of trusting struct padding */
struct {
u_int8_t version;
u_int8_t command;
u_int8_t reserved;
u_int8_t atyp;
} s5_req, s5_rsp;
u_int16_t dest_port;
char dest_addr[255+1], ntop[INET6_ADDRSTRLEN];
const u_char *p;
u_int have, need, i, found, nmethods, addrlen, af;
int r;
debug2("channel %d: decode socks5", c->self);
p = sshbuf_ptr(input);
if (p[0] != 0x05)
return -1;
have = sshbuf_len(input);
if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {
/* format: ver | nmethods | methods */
if (have < 2)
return 0;
nmethods = p[1];
if (have < nmethods + 2)
return 0;
/* look for method: "NO AUTHENTICATION REQUIRED" */
for (found = 0, i = 2; i < nmethods + 2; i++) {
if (p[i] == SSH_SOCKS5_NOAUTH) {
found = 1;
break;
}
}
if (!found) {
debug("channel %d: method SSH_SOCKS5_NOAUTH not found",
c->self);
return -1;
}
if ((r = sshbuf_consume(input, nmethods + 2)) != 0) {
fatal("%s: channel %d: consume: %s", __func__,
c->self, ssh_err(r));
}
/* version, method */
if ((r = sshbuf_put_u8(output, 0x05)) != 0 ||
(r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) {
fatal("%s: channel %d: append reply: %s", __func__,
c->self, ssh_err(r));
}
c->flags |= SSH_SOCKS5_AUTHDONE;
debug2("channel %d: socks5 auth done", c->self);
return 0; /* need more */
}
debug2("channel %d: socks5 post auth", c->self);
if (have < sizeof(s5_req)+1)
return 0; /* need more */
memcpy(&s5_req, p, sizeof(s5_req));
if (s5_req.version != 0x05 ||
s5_req.command != SSH_SOCKS5_CONNECT ||
s5_req.reserved != 0x00) {
debug2("channel %d: only socks5 connect supported", c->self);
return -1;
}
switch (s5_req.atyp){
case SSH_SOCKS5_IPV4:
addrlen = 4;
af = AF_INET;
break;
case SSH_SOCKS5_DOMAIN:
addrlen = p[sizeof(s5_req)];
af = -1;
break;
case SSH_SOCKS5_IPV6:
addrlen = 16;
af = AF_INET6;
break;
default:
debug2("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp);
return -1;
}
need = sizeof(s5_req) + addrlen + 2;
if (s5_req.atyp == SSH_SOCKS5_DOMAIN)
need++;
if (have < need)
return 0;
if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) {
fatal("%s: channel %d: consume: %s", __func__,
c->self, ssh_err(r));
}
if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {
/* host string length */
if ((r = sshbuf_consume(input, 1)) != 0) {
fatal("%s: channel %d: consume: %s", __func__,
c->self, ssh_err(r));
}
}
if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 ||
(r = sshbuf_get(input, &dest_port, 2)) != 0) {
debug("channel %d: parse addr/port: %s", c->self, ssh_err(r));
return -1;
}
dest_addr[addrlen] = '\0';
free(c->path);
c->path = NULL;
if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {
if (addrlen >= NI_MAXHOST) {
error("channel %d: dynamic request: socks5 hostname "
"\"%.100s\" too long", c->self, dest_addr);
return -1;
}
c->path = xstrdup(dest_addr);
} else {
if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL)
return -1;
c->path = xstrdup(ntop);
}
c->host_port = ntohs(dest_port);
debug2("channel %d: dynamic request: socks5 host %s port %u command %u",
c->self, c->path, c->host_port, s5_req.command);
s5_rsp.version = 0x05;
s5_rsp.command = SSH_SOCKS5_SUCCESS;
s5_rsp.reserved = 0; /* ignored */
s5_rsp.atyp = SSH_SOCKS5_IPV4;
dest_port = 0; /* ignored */
if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 ||
(r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 ||
(r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0)
fatal("%s: channel %d: append reply: %s", __func__,
c->self, ssh_err(r));
return 1;
}
Channel *
channel_connect_stdio_fwd(struct ssh *ssh,
const char *host_to_connect, u_short port_to_connect, int in, int out)
{
Channel *c;
debug("%s %s:%d", __func__, host_to_connect, port_to_connect);
c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out,
-1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "stdio-forward", /*nonblock*/0);
c->path = xstrdup(host_to_connect);
c->host_port = port_to_connect;
c->listening_port = 0;
c->force_drain = 1;
channel_register_fds(ssh, c, in, out, -1, 0, 1, 0);
port_open_helper(ssh, c, "direct-tcpip");
return c;
}
/* dynamic port forwarding */
static void
channel_pre_dynamic(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
const u_char *p;
u_int have;
int ret;
have = sshbuf_len(c->input);
debug2("channel %d: pre_dynamic: have %d", c->self, have);
/* sshbuf_dump(c->input, stderr); */
/* check if the fixed size part of the packet is in buffer. */
if (have < 3) {
/* need more */
FD_SET(c->sock, readset);
return;
}
/* try to guess the protocol */
p = sshbuf_ptr(c->input);
/* XXX sshbuf_peek_u8? */
switch (p[0]) {
case 0x04:
ret = channel_decode_socks4(c, c->input, c->output);
break;
case 0x05:
ret = channel_decode_socks5(c, c->input, c->output);
break;
default:
ret = -1;
break;
}
if (ret < 0) {
chan_mark_dead(ssh, c);
} else if (ret == 0) {
debug2("channel %d: pre_dynamic: need more", c->self);
/* need more */
FD_SET(c->sock, readset);
if (sshbuf_len(c->output))
FD_SET(c->sock, writeset);
} else {
/* switch to the next state */
c->type = SSH_CHANNEL_OPENING;
port_open_helper(ssh, c, "direct-tcpip");
}
}
/* simulate read-error */
static void
rdynamic_close(struct ssh *ssh, Channel *c)
{
c->type = SSH_CHANNEL_OPEN;
chan_read_failed(ssh, c);
sshbuf_reset(c->input);
chan_ibuf_empty(ssh, c);
sshbuf_reset(c->output);
chan_write_failed(ssh, c);
}
/* reverse dynamic port forwarding */
static void
channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c)
{
const u_char *p;
u_int have, len;
int r, ret;
have = sshbuf_len(c->output);
debug2("channel %d: pre_rdynamic: have %d", c->self, have);
/* sshbuf_dump(c->output, stderr); */
/* EOF received */
if (c->flags & CHAN_EOF_RCVD) {
if ((r = sshbuf_consume(c->output, have)) != 0) {
fatal("%s: channel %d: consume: %s",
__func__, c->self, ssh_err(r));
}
rdynamic_close(ssh, c);
return;
}
/* check if the fixed size part of the packet is in buffer. */
if (have < 3)
return;
/* try to guess the protocol */
p = sshbuf_ptr(c->output);
switch (p[0]) {
case 0x04:
/* switch input/output for reverse forwarding */
ret = channel_decode_socks4(c, c->output, c->input);
break;
case 0x05:
ret = channel_decode_socks5(c, c->output, c->input);
break;
default:
ret = -1;
break;
}
if (ret < 0) {
rdynamic_close(ssh, c);
} else if (ret == 0) {
debug2("channel %d: pre_rdynamic: need more", c->self);
/* send socks request to peer */
len = sshbuf_len(c->input);
if (len > 0 && len < c->remote_window) {
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_stringb(ssh, c->input)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
fatal("%s: channel %i: rdynamic: %s", __func__,
c->self, ssh_err(r));
}
if ((r = sshbuf_consume(c->input, len)) != 0) {
fatal("%s: channel %d: consume: %s",
__func__, c->self, ssh_err(r));
}
c->remote_window -= len;
}
} else if (rdynamic_connect_finish(ssh, c) < 0) {
/* the connect failed */
rdynamic_close(ssh, c);
}
}
/* This is our fake X11 server socket. */
static void
channel_post_x11_listener(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
Channel *nc;
struct sockaddr_storage addr;
int r, newsock, oerrno, remote_port;
socklen_t addrlen;
char buf[16384], *remote_ipaddr;
if (!FD_ISSET(c->sock, readset))
return;
debug("X11 connection requested.");
addrlen = sizeof(addr);
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
if (c->single_connection) {
oerrno = errno;
debug2("single_connection: closing X11 listener.");
channel_close_fd(ssh, &c->sock);
chan_mark_dead(ssh, c);
errno = oerrno;
}
if (newsock < 0) {
if (errno != EINTR && errno != EWOULDBLOCK &&
errno != ECONNABORTED)
error("accept: %.100s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
c->notbefore = monotime() + 1;
return;
}
set_nodelay(newsock);
remote_ipaddr = get_peer_ipaddr(newsock);
remote_port = get_peer_port(newsock);
snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
remote_ipaddr, remote_port);
nc = channel_new(ssh, "accepted x11 socket",
SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket, 0, buf, 1);
open_preamble(ssh, __func__, nc, "x11");
if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
(r = sshpkt_put_u32(ssh, remote_port)) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
free(remote_ipaddr);
}
static void
port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
{
char *local_ipaddr = get_local_ipaddr(c->sock);
int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock);
char *remote_ipaddr = get_peer_ipaddr(c->sock);
int remote_port = get_peer_port(c->sock);
int r;
if (remote_port == -1) {
/* Fake addr/port to appease peers that validate it (Tectia) */
free(remote_ipaddr);
remote_ipaddr = xstrdup("127.0.0.1");
remote_port = 65535;
}
free(c->remote_name);
xasprintf(&c->remote_name,
"%s: listening port %d for %.100s port %d, "
"connect from %.200s port %d to %.100s port %d",
rtype, c->listening_port, c->path, c->host_port,
remote_ipaddr, remote_port, local_ipaddr, local_port);
open_preamble(ssh, __func__, c, rtype);
if (strcmp(rtype, "direct-tcpip") == 0) {
/* target host, port */
if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
(r = sshpkt_put_u32(ssh, c->host_port)) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
} else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
/* target path */
if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
} else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* listen path */
if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
} else {
/* listen address, port */
if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
(r = sshpkt_put_u32(ssh, local_port)) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
}
if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* reserved for future owner/mode info */
if ((r = sshpkt_put_cstring(ssh, "")) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
} else {
/* originator host and port */
if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) {
fatal("%s: channel %i: reply %s", __func__,
c->self, ssh_err(r));
}
}
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
free(remote_ipaddr);
free(local_ipaddr);
}
void
channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time)
{
ssh->chanctxt->x11_refuse_time = refuse_time;
}
/*
* This socket is listening for connections to a forwarded TCP/IP port.
*/
static void
channel_post_port_listener(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
Channel *nc;
struct sockaddr_storage addr;
int newsock, nextstate;
socklen_t addrlen;
char *rtype;
if (!FD_ISSET(c->sock, readset))
return;
debug("Connection to port %d forwarding to %.100s port %d requested.",
c->listening_port, c->path, c->host_port);
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
nextstate = SSH_CHANNEL_OPENING;
rtype = "forwarded-tcpip";
} else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
nextstate = SSH_CHANNEL_OPENING;
rtype = "forwarded-streamlocal@openssh.com";
} else if (c->host_port == PORT_STREAMLOCAL) {
nextstate = SSH_CHANNEL_OPENING;
rtype = "direct-streamlocal@openssh.com";
} else if (c->host_port == 0) {
nextstate = SSH_CHANNEL_DYNAMIC;
rtype = "dynamic-tcpip";
} else {
nextstate = SSH_CHANNEL_OPENING;
rtype = "direct-tcpip";
}
addrlen = sizeof(addr);
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
if (newsock < 0) {
if (errno != EINTR && errno != EWOULDBLOCK &&
errno != ECONNABORTED)
error("accept: %.100s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
c->notbefore = monotime() + 1;
return;
}
if (c->host_port != PORT_STREAMLOCAL)
set_nodelay(newsock);
nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket, 0, rtype, 1);
nc->listening_port = c->listening_port;
nc->host_port = c->host_port;
if (c->path != NULL)
nc->path = xstrdup(c->path);
if (nextstate != SSH_CHANNEL_DYNAMIC)
port_open_helper(ssh, nc, rtype);
}
/*
* This is the authentication agent socket listening for connections from
* clients.
*/
static void
channel_post_auth_listener(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
Channel *nc;
int r, newsock;
struct sockaddr_storage addr;
socklen_t addrlen;
if (!FD_ISSET(c->sock, readset))
return;
addrlen = sizeof(addr);
newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
if (newsock < 0) {
error("accept from auth socket: %.100s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
c->notbefore = monotime() + 1;
return;
}
nc = channel_new(ssh, "accepted auth socket",
SSH_CHANNEL_OPENING, newsock, newsock, -1,
c->local_window_max, c->local_maxpacket,
0, "accepted auth socket", 1);
open_preamble(ssh, __func__, nc, "auth-agent@openssh.com");
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
}
static void
channel_post_connecting(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
int err = 0, sock, isopen, r;
socklen_t sz = sizeof(err);
if (!FD_ISSET(c->sock, writeset))
return;
if (!c->have_remote_id)
fatal(":%s: channel %d: no remote id", __func__, c->self);
/* for rdynamic the OPEN_CONFIRMATION has been sent already */
isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH);
if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {
err = errno;
error("getsockopt SO_ERROR failed");
}
if (err == 0) {
debug("channel %d: connected to %s port %d",
c->self, c->connect_ctx.host, c->connect_ctx.port);
channel_connect_ctx_free(&c->connect_ctx);
c->type = SSH_CHANNEL_OPEN;
if (isopen) {
/* no message necessary */
} else {
if ((r = sshpkt_start(ssh,
SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->self)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_maxpacket))
!= 0)
fatal("%s: channel %i: confirm: %s", __func__,
c->self, ssh_err(r));
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: %s", __func__, c->self,
ssh_err(r));
}
} else {
debug("channel %d: connection failed: %s",
c->self, strerror(err));
/* Try next address, if any */
if ((sock = connect_next(&c->connect_ctx)) > 0) {
close(c->sock);
c->sock = c->rfd = c->wfd = sock;
channel_find_maxfd(ssh->chanctxt);
return;
}
/* Exhausted all addresses */
error("connect_to %.100s port %d: failed.",
c->connect_ctx.host, c->connect_ctx.port);
channel_connect_ctx_free(&c->connect_ctx);
if (isopen) {
rdynamic_close(ssh, c);
} else {
if ((r = sshpkt_start(ssh,
SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh,
SSH2_OPEN_CONNECT_FAILED)) != 0 ||
(r = sshpkt_put_cstring(ssh, strerror(err))) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0) {
fatal("%s: channel %i: failure: %s", __func__,
c->self, ssh_err(r));
}
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %i: %s", __func__, c->self,
ssh_err(r));
chan_mark_dead(ssh, c);
}
}
}
static int
channel_handle_rfd(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
char buf[CHAN_RBUF];
ssize_t len;
int r, force;
force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
if (c->rfd == -1 || (!force && !FD_ISSET(c->rfd, readset)))
return 1;
errno = 0;
len = read(c->rfd, buf, sizeof(buf));
if (len < 0 && (errno == EINTR ||
((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
return 1;
#ifndef PTY_ZEROREAD
if (len <= 0) {
#else
if ((!c->isatty && len <= 0) ||
(c->isatty && (len < 0 || (len == 0 && errno != 0)))) {
#endif
debug2("channel %d: read<=0 rfd %d len %zd",
c->self, c->rfd, len);
if (c->type != SSH_CHANNEL_OPEN) {
debug2("channel %d: not open", c->self);
chan_mark_dead(ssh, c);
return -1;
} else {
chan_read_failed(ssh, c);
}
return -1;
}
if (c->input_filter != NULL) {
if (c->input_filter(ssh, c, buf, len) == -1) {
debug2("channel %d: filter stops", c->self);
chan_read_failed(ssh, c);
}
} else if (c->datagram) {
if ((r = sshbuf_put_string(c->input, buf, len)) != 0)
fatal("%s: channel %d: put datagram: %s", __func__,
c->self, ssh_err(r));
} else if ((r = sshbuf_put(c->input, buf, len)) != 0) {
fatal("%s: channel %d: put data: %s", __func__,
c->self, ssh_err(r));
}
return 1;
}
static int
channel_handle_wfd(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
struct termios tio;
u_char *data = NULL, *buf; /* XXX const; need filter API change */
size_t dlen, olen = 0;
int r, len;
if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||
sshbuf_len(c->output) == 0)
return 1;
/* Send buffered output data to the socket. */
olen = sshbuf_len(c->output);
if (c->output_filter != NULL) {
if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) {
debug2("channel %d: filter stops", c->self);
if (c->type != SSH_CHANNEL_OPEN)
chan_mark_dead(ssh, c);
else
chan_write_failed(ssh, c);
return -1;
}
} else if (c->datagram) {
if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0)
fatal("%s: channel %d: get datagram: %s", __func__,
c->self, ssh_err(r));
buf = data;
} else {
buf = data = sshbuf_mutable_ptr(c->output);
dlen = sshbuf_len(c->output);
}
if (c->datagram) {
/* ignore truncated writes, datagrams might get lost */
len = write(c->wfd, buf, dlen);
free(data);
if (len < 0 && (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK))
return 1;
if (len <= 0)
goto write_fail;
goto out;
}
#ifdef _AIX
/* XXX: Later AIX versions can't push as much data to tty */
if (c->wfd_isatty)
dlen = MIN(dlen, 8*1024);
#endif
len = write(c->wfd, buf, dlen);
if (len < 0 &&
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
return 1;
if (len <= 0) {
write_fail:
if (c->type != SSH_CHANNEL_OPEN) {
debug2("channel %d: not open", c->self);
chan_mark_dead(ssh, c);
return -1;
} else {
chan_write_failed(ssh, c);
}
return -1;
}
#ifndef BROKEN_TCGETATTR_ICANON
if (c->isatty && dlen >= 1 && buf[0] != '\r') {
if (tcgetattr(c->wfd, &tio) == 0 &&
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
/*
* Simulate echo to reduce the impact of
* traffic analysis. We need to match the
* size of a SSH2_MSG_CHANNEL_DATA message
* (4 byte channel id + buf)
*/
if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %d: ignore: %s",
__func__, c->self, ssh_err(r));
}
}
#endif /* BROKEN_TCGETATTR_ICANON */
if ((r = sshbuf_consume(c->output, len)) != 0) {
fatal("%s: channel %d: consume: %s",
__func__, c->self, ssh_err(r));
}
out:
c->local_consumed += olen - sshbuf_len(c->output);
return 1;
}
static int
channel_handle_efd_write(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
int r;
ssize_t len;
if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0)
return 1;
len = write(c->efd, sshbuf_ptr(c->extended),
sshbuf_len(c->extended));
debug2("channel %d: written %zd to efd %d", c->self, len, c->efd);
if (len < 0 && (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK))
return 1;
if (len <= 0) {
debug2("channel %d: closing write-efd %d", c->self, c->efd);
channel_close_fd(ssh, &c->efd);
} else {
if ((r = sshbuf_consume(c->extended, len)) != 0) {
fatal("%s: channel %d: consume: %s",
__func__, c->self, ssh_err(r));
}
c->local_consumed += len;
}
return 1;
}
static int
channel_handle_efd_read(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
char buf[CHAN_RBUF];
- int r;
ssize_t len;
+ int r, force;
+
+ force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
- if (!c->detach_close && !FD_ISSET(c->efd, readset))
+ if (c->efd == -1 || (!force && !FD_ISSET(c->efd, readset)))
return 1;
len = read(c->efd, buf, sizeof(buf));
debug2("channel %d: read %zd from efd %d", c->self, len, c->efd);
if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
- errno == EWOULDBLOCK) && !c->detach_close)))
+ errno == EWOULDBLOCK) && !force)))
return 1;
if (len <= 0) {
debug2("channel %d: closing read-efd %d",
c->self, c->efd);
channel_close_fd(ssh, &c->efd);
} else {
if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
debug3("channel %d: discard efd",
c->self);
} else if ((r = sshbuf_put(c->extended, buf, len)) != 0) {
fatal("%s: channel %d: append: %s",
__func__, c->self, ssh_err(r));
}
}
return 1;
}
static int
channel_handle_efd(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
if (c->efd == -1)
return 1;
/** XXX handle drain efd, too */
if (c->extended_usage == CHAN_EXTENDED_WRITE)
return channel_handle_efd_write(ssh, c, readset, writeset);
else if (c->extended_usage == CHAN_EXTENDED_READ ||
c->extended_usage == CHAN_EXTENDED_IGNORE)
return channel_handle_efd_read(ssh, c, readset, writeset);
return 1;
}
static int
channel_check_window(struct ssh *ssh, Channel *c)
{
int r;
if (c->type == SSH_CHANNEL_OPEN &&
!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
((c->local_window_max - c->local_window >
c->local_maxpacket*3) ||
c->local_window < c->local_window_max/2) &&
c->local_consumed > 0) {
if (!c->have_remote_id)
fatal(":%s: channel %d: no remote id",
__func__, c->self);
if ((r = sshpkt_start(ssh,
SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
fatal("%s: channel %i: %s", __func__,
c->self, ssh_err(r));
}
debug2("channel %d: window %d sent adjust %d",
c->self, c->local_window,
c->local_consumed);
c->local_window += c->local_consumed;
c->local_consumed = 0;
}
return 1;
}
static void
channel_post_open(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
channel_handle_rfd(ssh, c, readset, writeset);
channel_handle_wfd(ssh, c, readset, writeset);
channel_handle_efd(ssh, c, readset, writeset);
channel_check_window(ssh, c);
}
static u_int
read_mux(struct ssh *ssh, Channel *c, u_int need)
{
char buf[CHAN_RBUF];
ssize_t len;
u_int rlen;
int r;
if (sshbuf_len(c->input) < need) {
rlen = need - sshbuf_len(c->input);
len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF));
if (len < 0 && (errno == EINTR || errno == EAGAIN))
return sshbuf_len(c->input);
if (len <= 0) {
debug2("channel %d: ctl read<=0 rfd %d len %zd",
c->self, c->rfd, len);
chan_read_failed(ssh, c);
return 0;
} else if ((r = sshbuf_put(c->input, buf, len)) != 0) {
fatal("%s: channel %d: append: %s",
__func__, c->self, ssh_err(r));
}
}
return sshbuf_len(c->input);
}
static void
channel_post_mux_client_read(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
u_int need;
if (c->rfd == -1 || !FD_ISSET(c->rfd, readset))
return;
if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN)
return;
if (c->mux_pause)
return;
/*
* Don't not read past the precise end of packets to
* avoid disrupting fd passing.
*/
if (read_mux(ssh, c, 4) < 4) /* read header */
return;
/* XXX sshbuf_peek_u32 */
need = PEEK_U32(sshbuf_ptr(c->input));
#define CHANNEL_MUX_MAX_PACKET (256 * 1024)
if (need > CHANNEL_MUX_MAX_PACKET) {
debug2("channel %d: packet too big %u > %u",
c->self, CHANNEL_MUX_MAX_PACKET, need);
chan_rcvd_oclose(ssh, c);
return;
}
if (read_mux(ssh, c, need + 4) < need + 4) /* read body */
return;
if (c->mux_rcb(ssh, c) != 0) {
debug("channel %d: mux_rcb failed", c->self);
chan_mark_dead(ssh, c);
return;
}
}
static void
channel_post_mux_client_write(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
ssize_t len;
int r;
if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||
sshbuf_len(c->output) == 0)
return;
len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output));
if (len < 0 && (errno == EINTR || errno == EAGAIN))
return;
if (len <= 0) {
chan_mark_dead(ssh, c);
return;
}
if ((r = sshbuf_consume(c->output, len)) != 0)
fatal("%s: channel %d: consume: %s", __func__,
c->self, ssh_err(r));
}
static void
channel_post_mux_client(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
channel_post_mux_client_read(ssh, c, readset, writeset);
channel_post_mux_client_write(ssh, c, readset, writeset);
}
static void
channel_post_mux_listener(struct ssh *ssh, Channel *c,
fd_set *readset, fd_set *writeset)
{
Channel *nc;
struct sockaddr_storage addr;
socklen_t addrlen;
int newsock;
uid_t euid;
gid_t egid;
if (!FD_ISSET(c->sock, readset))
return;
debug("multiplexing control connection");
/*
* Accept connection on control socket
*/
memset(&addr, 0, sizeof(addr));
addrlen = sizeof(addr);
if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
&addrlen)) == -1) {
error("%s accept: %s", __func__, strerror(errno));
if (errno == EMFILE || errno == ENFILE)
c->notbefore = monotime() + 1;
return;
}
if (getpeereid(newsock, &euid, &egid) < 0) {
error("%s getpeereid failed: %s", __func__,
strerror(errno));
close(newsock);
return;
}
if ((euid != 0) && (getuid() != euid)) {
error("multiplex uid mismatch: peer euid %u != uid %u",
(u_int)euid, (u_int)getuid());
close(newsock);
return;
}
nc = channel_new(ssh, "multiplex client", SSH_CHANNEL_MUX_CLIENT,
newsock, newsock, -1, c->local_window_max,
c->local_maxpacket, 0, "mux-control", 1);
nc->mux_rcb = c->mux_rcb;
debug3("%s: new mux channel %d fd %d", __func__, nc->self, nc->sock);
/* establish state */
nc->mux_rcb(ssh, nc);
/* mux state transitions must not elicit protocol messages */
nc->flags |= CHAN_LOCAL;
}
static void
channel_handler_init(struct ssh_channels *sc)
{
chan_fn **pre, **post;
if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL ||
(post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL)
fatal("%s: allocation failed", __func__);
pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting;
pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
post[SSH_CHANNEL_OPEN] = &channel_post_open;
post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting;
post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
sc->channel_pre = pre;
sc->channel_post = post;
}
/* gc dead channels */
static void
channel_garbage_collect(struct ssh *ssh, Channel *c)
{
if (c == NULL)
return;
if (c->detach_user != NULL) {
if (!chan_is_dead(ssh, c, c->detach_close))
return;
debug2("channel %d: gc: notify user", c->self);
c->detach_user(ssh, c->self, NULL);
/* if we still have a callback */
if (c->detach_user != NULL)
return;
debug2("channel %d: gc: user detached", c->self);
}
if (!chan_is_dead(ssh, c, 1))
return;
debug2("channel %d: garbage collecting", c->self);
channel_free(ssh, c);
}
enum channel_table { CHAN_PRE, CHAN_POST };
static void
channel_handler(struct ssh *ssh, int table,
fd_set *readset, fd_set *writeset, time_t *unpause_secs)
{
struct ssh_channels *sc = ssh->chanctxt;
chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;
u_int i, oalloc;
Channel *c;
time_t now;
now = monotime();
if (unpause_secs != NULL)
*unpause_secs = 0;
for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
c = sc->channels[i];
if (c == NULL)
continue;
if (c->delayed) {
if (table == CHAN_PRE)
c->delayed = 0;
else
continue;
}
if (ftab[c->type] != NULL) {
/*
* Run handlers that are not paused.
*/
if (c->notbefore <= now)
(*ftab[c->type])(ssh, c, readset, writeset);
else if (unpause_secs != NULL) {
/*
* Collect the time that the earliest
* channel comes off pause.
*/
debug3("%s: chan %d: skip for %d more seconds",
__func__, c->self,
(int)(c->notbefore - now));
if (*unpause_secs == 0 ||
(c->notbefore - now) < *unpause_secs)
*unpause_secs = c->notbefore - now;
}
}
channel_garbage_collect(ssh, c);
}
if (unpause_secs != NULL && *unpause_secs != 0)
debug3("%s: first channel unpauses in %d seconds",
__func__, (int)*unpause_secs);
}
/*
* Create sockets before allocating the select bitmasks.
* This is necessary for things that need to happen after reading
* the network-input but before channel_prepare_select().
*/
static void
channel_before_prepare_select(struct ssh *ssh)
{
struct ssh_channels *sc = ssh->chanctxt;
Channel *c;
u_int i, oalloc;
for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {
c = sc->channels[i];
if (c == NULL)
continue;
if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN)
channel_before_prepare_select_rdynamic(ssh, c);
}
}
/*
* Allocate/update select bitmasks and add any bits relevant to channels in
* select bitmasks.
*/
void
channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp,
int *maxfdp, u_int *nallocp, time_t *minwait_secs)
{
u_int n, sz, nfdset;
channel_before_prepare_select(ssh); /* might update channel_max_fd */
n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd);
nfdset = howmany(n+1, NFDBITS);
/* Explicitly test here, because xrealloc isn't always called */
if (nfdset && SIZE_MAX / nfdset < sizeof(fd_mask))
fatal("channel_prepare_select: max_fd (%d) is too large", n);
sz = nfdset * sizeof(fd_mask);
/* perhaps check sz < nalloc/2 and shrink? */
if (*readsetp == NULL || sz > *nallocp) {
*readsetp = xreallocarray(*readsetp, nfdset, sizeof(fd_mask));
*writesetp = xreallocarray(*writesetp, nfdset, sizeof(fd_mask));
*nallocp = sz;
}
*maxfdp = n;
memset(*readsetp, 0, sz);
memset(*writesetp, 0, sz);
if (!ssh_packet_is_rekeying(ssh))
channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp,
minwait_secs);
}
/*
* After select, perform any appropriate operations for channels which have
* events pending.
*/
void
channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset)
{
channel_handler(ssh, CHAN_POST, readset, writeset, NULL);
}
/*
* Enqueue data for channels with open or draining c->input.
*/
static void
channel_output_poll_input_open(struct ssh *ssh, Channel *c)
{
size_t len, plen;
const u_char *pkt;
int r;
if ((len = sshbuf_len(c->input)) == 0) {
if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
/*
* input-buffer is empty and read-socket shutdown:
* tell peer, that we will not send more data:
* send IEOF.
* hack for extended data: delay EOF if EFD still
* in use.
*/
if (CHANNEL_EFD_INPUT_ACTIVE(c))
debug2("channel %d: "
"ibuf_empty delayed efd %d/(%zu)",
c->self, c->efd, sshbuf_len(c->extended));
else
chan_ibuf_empty(ssh, c);
}
return;
}
if (!c->have_remote_id)
fatal(":%s: channel %d: no remote id", __func__, c->self);
if (c->datagram) {
/* Check datagram will fit; drop if not */
if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0)
fatal("%s: channel %d: get datagram: %s", __func__,
c->self, ssh_err(r));
/*
* XXX this does tail-drop on the datagram queue which is
* usually suboptimal compared to head-drop. Better to have
* backpressure at read time? (i.e. read + discard)
*/
if (plen > c->remote_window || plen > c->remote_maxpacket) {
debug("channel %d: datagram too big", c->self);
return;
}
/* Enqueue it */
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_string(ssh, pkt, plen)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
fatal("%s: channel %i: datagram: %s", __func__,
c->self, ssh_err(r));
}
c->remote_window -= plen;
return;
}
/* Enqueue packet for buffered data. */
if (len > c->remote_window)
len = c->remote_window;
if (len > c->remote_maxpacket)
len = c->remote_maxpacket;
if (len == 0)
return;
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
fatal("%s: channel %i: data: %s", __func__,
c->self, ssh_err(r));
}
if ((r = sshbuf_consume(c->input, len)) != 0)
fatal("%s: channel %i: consume: %s", __func__,
c->self, ssh_err(r));
c->remote_window -= len;
}
/*
* Enqueue data for channels with open c->extended in read mode.
*/
static void
channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
{
size_t len;
int r;
if ((len = sshbuf_len(c->extended)) == 0)
return;
debug2("channel %d: rwin %u elen %zu euse %d", c->self,
c->remote_window, sshbuf_len(c->extended), c->extended_usage);
if (len > c->remote_window)
len = c->remote_window;
if (len > c->remote_maxpacket)
len = c->remote_maxpacket;
if (len == 0)
return;
if (!c->have_remote_id)
fatal(":%s: channel %d: no remote id", __func__, c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 ||
(r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
fatal("%s: channel %i: data: %s", __func__,
c->self, ssh_err(r));
}
if ((r = sshbuf_consume(c->extended, len)) != 0)
fatal("%s: channel %i: consume: %s", __func__,
c->self, ssh_err(r));
c->remote_window -= len;
debug2("channel %d: sent ext data %zu", c->self, len);
}
/* If there is data to send to the connection, enqueue some of it now. */
void
channel_output_poll(struct ssh *ssh)
{
struct ssh_channels *sc = ssh->chanctxt;
Channel *c;
u_int i;
for (i = 0; i < sc->channels_alloc; i++) {
c = sc->channels[i];
if (c == NULL)
continue;
/*
* We are only interested in channels that can have buffered
* incoming data.
*/
if (c->type != SSH_CHANNEL_OPEN)
continue;
if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {
/* XXX is this true? */
debug3("channel %d: will not send data after close",
c->self);
continue;
}
/* Get the amount of buffered data for this channel. */
if (c->istate == CHAN_INPUT_OPEN ||
c->istate == CHAN_INPUT_WAIT_DRAIN)
channel_output_poll_input_open(ssh, c);
/* Send extended data, i.e. stderr */
if (!(c->flags & CHAN_EOF_SENT) &&
c->extended_usage == CHAN_EXTENDED_READ)
channel_output_poll_extended_read(ssh, c);
}
}
/* -- mux proxy support */
/*
* When multiplexing channel messages for mux clients we have to deal
* with downstream messages from the mux client and upstream messages
* from the ssh server:
* 1) Handling downstream messages is straightforward and happens
* in channel_proxy_downstream():
* - We forward all messages (mostly) unmodified to the server.
* - However, in order to route messages from upstream to the correct
* downstream client, we have to replace the channel IDs used by the
* mux clients with a unique channel ID because the mux clients might
* use conflicting channel IDs.
* - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and
* SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local
* SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID
* with the newly allocated channel ID.
* 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY
* channels and processed by channel_proxy_upstream(). The local channel ID
* is then translated back to the original mux client ID.
* 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE
* messages so we can clean up SSH_CHANNEL_MUX_PROXY channels.
* 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the
* downstream mux client are removed.
* 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server
* requires more work, because they are not addressed to a specific
* channel. E.g. client_request_forwarded_tcpip() needs to figure
* out whether the request is addressed to the local client or a
* specific downstream client based on the listen-address/port.
* 6) Agent and X11-Forwarding have a similar problem and are currently
* not supported as the matching session/channel cannot be identified
* easily.
*/
/*
* receive packets from downstream mux clients:
* channel callback fired on read from mux client, creates
* SSH_CHANNEL_MUX_PROXY channels and translates channel IDs
* on channel creation.
*/
int
channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
{
Channel *c = NULL;
struct sshbuf *original = NULL, *modified = NULL;
const u_char *cp;
char *ctype = NULL, *listen_host = NULL;
u_char type;
size_t have;
int ret = -1, r;
u_int id, remote_id, listen_port;
/* sshbuf_dump(downstream->input, stderr); */
if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have))
!= 0) {
error("%s: malformed message: %s", __func__, ssh_err(r));
return -1;
}
if (have < 2) {
error("%s: short message", __func__);
return -1;
}
type = cp[1];
/* skip padlen + type */
cp += 2;
have -= 2;
if (ssh_packet_log_type(type))
debug3("%s: channel %u: down->up: type %u", __func__,
downstream->self, type);
switch (type) {
case SSH2_MSG_CHANNEL_OPEN:
if ((original = sshbuf_from(cp, have)) == NULL ||
(modified = sshbuf_new()) == NULL) {
error("%s: alloc", __func__);
goto out;
}
if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 ||
(r = sshbuf_get_u32(original, &id)) != 0) {
error("%s: parse error %s", __func__, ssh_err(r));
goto out;
}
c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY,
-1, -1, -1, 0, 0, 0, ctype, 1);
c->mux_ctx = downstream; /* point to mux client */
c->mux_downstream_id = id; /* original downstream id */
if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||
(r = sshbuf_put_u32(modified, c->self)) != 0 ||
(r = sshbuf_putb(modified, original)) != 0) {
error("%s: compose error %s", __func__, ssh_err(r));
channel_free(ssh, c);
goto out;
}
break;
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
/*
* Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we
* need to parse 'remote_id' instead of 'ctype'.
*/
if ((original = sshbuf_from(cp, have)) == NULL ||
(modified = sshbuf_new()) == NULL) {
error("%s: alloc", __func__);
goto out;
}
if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||
(r = sshbuf_get_u32(original, &id)) != 0) {
error("%s: parse error %s", __func__, ssh_err(r));
goto out;
}
c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY,
-1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
c->mux_ctx = downstream; /* point to mux client */
c->mux_downstream_id = id;
c->remote_id = remote_id;
c->have_remote_id = 1;
if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||
(r = sshbuf_put_u32(modified, c->self)) != 0 ||
(r = sshbuf_putb(modified, original)) != 0) {
error("%s: compose error %s", __func__, ssh_err(r));
channel_free(ssh, c);
goto out;
}
break;
case SSH2_MSG_GLOBAL_REQUEST:
if ((original = sshbuf_from(cp, have)) == NULL) {
error("%s: alloc", __func__);
goto out;
}
if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) {
error("%s: parse error %s", __func__, ssh_err(r));
goto out;
}
if (strcmp(ctype, "tcpip-forward") != 0) {
error("%s: unsupported request %s", __func__, ctype);
goto out;
}
if ((r = sshbuf_get_u8(original, NULL)) != 0 ||
(r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 ||
(r = sshbuf_get_u32(original, &listen_port)) != 0) {
error("%s: parse error %s", __func__, ssh_err(r));
goto out;
}
if (listen_port > 65535) {
error("%s: tcpip-forward for %s: bad port %u",
__func__, listen_host, listen_port);
goto out;
}
/* Record that connection to this host/port is permitted. */
permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "<mux>", -1,
listen_host, NULL, (int)listen_port, downstream);
listen_host = NULL;
break;
case SSH2_MSG_CHANNEL_CLOSE:
if (have < 4)
break;
remote_id = PEEK_U32(cp);
if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) {
if (c->flags & CHAN_CLOSE_RCVD)
channel_free(ssh, c);
else
c->flags |= CHAN_CLOSE_SENT;
}
break;
}
if (modified) {
if ((r = sshpkt_start(ssh, type)) != 0 ||
(r = sshpkt_putb(ssh, modified)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
error("%s: send %s", __func__, ssh_err(r));
goto out;
}
} else {
if ((r = sshpkt_start(ssh, type)) != 0 ||
(r = sshpkt_put(ssh, cp, have)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
error("%s: send %s", __func__, ssh_err(r));
goto out;
}
}
ret = 0;
out:
free(ctype);
free(listen_host);
sshbuf_free(original);
sshbuf_free(modified);
return ret;
}
/*
* receive packets from upstream server and de-multiplex packets
* to correct downstream:
* implemented as a helper for channel input handlers,
* replaces local (proxy) channel ID with downstream channel ID.
*/
int
channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh)
{
struct sshbuf *b = NULL;
Channel *downstream;
const u_char *cp = NULL;
size_t len;
int r;
/*
* When receiving packets from the peer we need to check whether we
* need to forward the packets to the mux client. In this case we
* restore the original channel id and keep track of CLOSE messages,
* so we can cleanup the channel.
*/
if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY)
return 0;
if ((downstream = c->mux_ctx) == NULL)
return 0;
switch (type) {
case SSH2_MSG_CHANNEL_CLOSE:
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EOF:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
case SSH2_MSG_CHANNEL_OPEN_FAILURE:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
case SSH2_MSG_CHANNEL_SUCCESS:
case SSH2_MSG_CHANNEL_FAILURE:
case SSH2_MSG_CHANNEL_REQUEST:
break;
default:
debug2("%s: channel %u: unsupported type %u", __func__,
c->self, type);
return 0;
}
if ((b = sshbuf_new()) == NULL) {
error("%s: alloc reply", __func__);
goto out;
}
/* get remaining payload (after id) */
cp = sshpkt_ptr(ssh, &len);
if (cp == NULL) {
error("%s: no packet", __func__);
goto out;
}
/* translate id and send to muxclient */
if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
(r = sshbuf_put_u8(b, type)) != 0 ||
(r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||
(r = sshbuf_put(b, cp, len)) != 0 ||
(r = sshbuf_put_stringb(downstream->output, b)) != 0) {
error("%s: compose for muxclient %s", __func__, ssh_err(r));
goto out;
}
/* sshbuf_dump(b, stderr); */
if (ssh_packet_log_type(type))
debug3("%s: channel %u: up->down: type %u", __func__, c->self,
type);
out:
/* update state */
switch (type) {
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
/* record remote_id for SSH2_MSG_CHANNEL_CLOSE */
if (cp && len > 4) {
c->remote_id = PEEK_U32(cp);
c->have_remote_id = 1;
}
break;
case SSH2_MSG_CHANNEL_CLOSE:
if (c->flags & CHAN_CLOSE_SENT)
channel_free(ssh, c);
else
c->flags |= CHAN_CLOSE_RCVD;
break;
}
sshbuf_free(b);
return 1;
}
/* -- protocol input */
/* Parse a channel ID from the current packet */
static int
channel_parse_id(struct ssh *ssh, const char *where, const char *what)
{
u_int32_t id;
int r;
if ((r = sshpkt_get_u32(ssh, &id)) != 0) {
error("%s: parse id: %s", where, ssh_err(r));
ssh_packet_disconnect(ssh, "Invalid %s message", what);
}
if (id > INT_MAX) {
error("%s: bad channel id %u: %s", where, id, ssh_err(r));
ssh_packet_disconnect(ssh, "Invalid %s channel id", what);
}
return (int)id;
}
/* Lookup a channel from an ID in the current packet */
static Channel *
channel_from_packet_id(struct ssh *ssh, const char *where, const char *what)
{
int id = channel_parse_id(ssh, where, what);
Channel *c;
if ((c = channel_lookup(ssh, id)) == NULL) {
ssh_packet_disconnect(ssh,
"%s packet referred to nonexistent channel %d", what, id);
}
return c;
}
int
channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
{
const u_char *data;
size_t data_len, win_len;
Channel *c = channel_from_packet_id(ssh, __func__, "data");
int r;
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
/* Ignore any data for non-open channels (might happen on close) */
if (c->type != SSH_CHANNEL_OPEN &&
c->type != SSH_CHANNEL_RDYNAMIC_OPEN &&
c->type != SSH_CHANNEL_RDYNAMIC_FINISH &&
c->type != SSH_CHANNEL_X11_OPEN)
return 0;
/* Get the data. */
- if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0)
+ if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
fatal("%s: channel %d: get data: %s", __func__,
c->self, ssh_err(r));
- ssh_packet_check_eom(ssh);
win_len = data_len;
if (c->datagram)
win_len += 4; /* string length header */
/*
* The sending side reduces its window as it sends data, so we
* must 'fake' consumption of the data in order to ensure that window
* updates are sent back. Otherwise the connection might deadlock.
*/
if (c->ostate != CHAN_OUTPUT_OPEN) {
c->local_window -= win_len;
c->local_consumed += win_len;
return 0;
}
if (win_len > c->local_maxpacket) {
logit("channel %d: rcvd big packet %zu, maxpack %u",
c->self, win_len, c->local_maxpacket);
return 0;
}
if (win_len > c->local_window) {
logit("channel %d: rcvd too much data %zu, win %u",
c->self, win_len, c->local_window);
return 0;
}
c->local_window -= win_len;
if (c->datagram) {
if ((r = sshbuf_put_string(c->output, data, data_len)) != 0)
fatal("%s: channel %d: append datagram: %s",
__func__, c->self, ssh_err(r));
} else if ((r = sshbuf_put(c->output, data, data_len)) != 0)
fatal("%s: channel %d: append data: %s",
__func__, c->self, ssh_err(r));
return 0;
}
int
channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
{
const u_char *data;
size_t data_len;
u_int32_t tcode;
Channel *c = channel_from_packet_id(ssh, __func__, "extended data");
int r;
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
if (c->type != SSH_CHANNEL_OPEN) {
logit("channel %d: ext data for non open", c->self);
return 0;
}
if (c->flags & CHAN_EOF_RCVD) {
if (datafellows & SSH_BUG_EXTEOF)
debug("channel %d: accepting ext data after eof",
c->self);
else
ssh_packet_disconnect(ssh, "Received extended_data "
"after EOF on channel %d.", c->self);
}
if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) {
error("%s: parse tcode: %s", __func__, ssh_err(r));
ssh_packet_disconnect(ssh, "Invalid extended_data message");
}
if (c->efd == -1 ||
c->extended_usage != CHAN_EXTENDED_WRITE ||
tcode != SSH2_EXTENDED_DATA_STDERR) {
logit("channel %d: bad ext data", c->self);
return 0;
}
- if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) {
+ if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
error("%s: parse data: %s", __func__, ssh_err(r));
ssh_packet_disconnect(ssh, "Invalid extended_data message");
}
- ssh_packet_check_eom(ssh);
if (data_len > c->local_window) {
logit("channel %d: rcvd too much extended_data %zu, win %u",
c->self, data_len, c->local_window);
return 0;
}
debug2("channel %d: rcvd ext data %zu", c->self, data_len);
/* XXX sshpkt_getb? */
if ((r = sshbuf_put(c->extended, data, data_len)) != 0)
error("%s: append: %s", __func__, ssh_err(r));
c->local_window -= data_len;
return 0;
}
int
channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = channel_from_packet_id(ssh, __func__, "ieof");
+ int r;
- ssh_packet_check_eom(ssh);
+ if ((r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: parse data: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid ieof message");
+ }
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
chan_rcvd_ieof(ssh, c);
/* XXX force input close */
if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {
debug("channel %d: FORCE input drain", c->self);
c->istate = CHAN_INPUT_WAIT_DRAIN;
if (sshbuf_len(c->input) == 0)
chan_ibuf_empty(ssh, c);
}
return 0;
}
int
channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = channel_from_packet_id(ssh, __func__, "oclose");
+ int r;
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
- ssh_packet_check_eom(ssh);
+ if ((r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: parse data: %s", __func__, ssh_err(r));
+ ssh_packet_disconnect(ssh, "Invalid oclose message");
+ }
chan_rcvd_oclose(ssh, c);
return 0;
}
int
channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation");
u_int32_t remote_window, remote_maxpacket;
int r;
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
if (c->type != SSH_CHANNEL_OPENING)
- packet_disconnect("Received open confirmation for "
+ ssh_packet_disconnect(ssh, "Received open confirmation for "
"non-opening channel %d.", c->self);
/*
* Record the remote channel number and mark that the channel
* is now open.
*/
if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 ||
(r = sshpkt_get_u32(ssh, &remote_window)) != 0 ||
- (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) {
+ (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
error("%s: window/maxpacket: %s", __func__, ssh_err(r));
- packet_disconnect("Invalid open confirmation message");
+ ssh_packet_disconnect(ssh, "Invalid open confirmation message");
}
- ssh_packet_check_eom(ssh);
c->have_remote_id = 1;
c->remote_window = remote_window;
c->remote_maxpacket = remote_maxpacket;
c->type = SSH_CHANNEL_OPEN;
if (c->open_confirm) {
debug2("%s: channel %d: callback start", __func__, c->self);
c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx);
debug2("%s: channel %d: callback done", __func__, c->self);
}
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
c->remote_window, c->remote_maxpacket);
return 0;
}
static char *
reason2txt(int reason)
{
switch (reason) {
case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED:
return "administratively prohibited";
case SSH2_OPEN_CONNECT_FAILED:
return "connect failed";
case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE:
return "unknown channel type";
case SSH2_OPEN_RESOURCE_SHORTAGE:
return "resource shortage";
}
return "unknown reason";
}
int
channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = channel_from_packet_id(ssh, __func__, "open failure");
u_int32_t reason;
char *msg = NULL;
int r;
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
if (c->type != SSH_CHANNEL_OPENING)
- packet_disconnect("Received open failure for "
+ ssh_packet_disconnect(ssh, "Received open failure for "
"non-opening channel %d.", c->self);
if ((r = sshpkt_get_u32(ssh, &reason)) != 0) {
error("%s: reason: %s", __func__, ssh_err(r));
- packet_disconnect("Invalid open failure message");
+ ssh_packet_disconnect(ssh, "Invalid open failure message");
}
/* skip language */
if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 ||
- (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0) {
+ (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
error("%s: message/lang: %s", __func__, ssh_err(r));
- packet_disconnect("Invalid open failure message");
+ ssh_packet_disconnect(ssh, "Invalid open failure message");
}
- ssh_packet_check_eom(ssh);
logit("channel %d: open failed: %s%s%s", c->self,
reason2txt(reason), msg ? ": ": "", msg ? msg : "");
free(msg);
if (c->open_confirm) {
debug2("%s: channel %d: callback start", __func__, c->self);
c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx);
debug2("%s: channel %d: callback done", __func__, c->self);
}
/* Schedule the channel for cleanup/deletion. */
chan_mark_dead(ssh, c);
return 0;
}
int
channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh)
{
int id = channel_parse_id(ssh, __func__, "window adjust");
Channel *c;
u_int32_t adjust;
u_int new_rwin;
int r;
if ((c = channel_lookup(ssh, id)) == NULL) {
logit("Received window adjust for non-open channel %d.", id);
return 0;
}
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
- if ((r = sshpkt_get_u32(ssh, &adjust)) != 0) {
+ if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0) {
error("%s: adjust: %s", __func__, ssh_err(r));
- packet_disconnect("Invalid window adjust message");
+ ssh_packet_disconnect(ssh, "Invalid window adjust message");
}
- ssh_packet_check_eom(ssh);
debug2("channel %d: rcvd adjust %u", c->self, adjust);
if ((new_rwin = c->remote_window + adjust) < c->remote_window) {
fatal("channel %d: adjust %u overflows remote window %u",
c->self, adjust, c->remote_window);
}
c->remote_window = new_rwin;
return 0;
}
int
channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh)
{
int id = channel_parse_id(ssh, __func__, "status confirm");
Channel *c;
struct channel_confirm *cc;
+ int r;
/* Reset keepalive timeout */
- packet_set_alive_timeouts(0);
+ ssh_packet_set_alive_timeouts(ssh, 0);
debug2("%s: type %d id %d", __func__, type, id);
if ((c = channel_lookup(ssh, id)) == NULL) {
logit("%s: %d: unknown", __func__, id);
return 0;
}
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
- ssh_packet_check_eom(ssh);
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ ssh_packet_disconnect(ssh, "Invalid status confirm message");
if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
return 0;
cc->cb(ssh, type, c, cc->ctx);
TAILQ_REMOVE(&c->status_confirms, cc, entry);
explicit_bzero(cc, sizeof(*cc));
free(cc);
return 0;
}
/* -- tcp forwarding */
void
channel_set_af(struct ssh *ssh, int af)
{
ssh->chanctxt->IPv4or6 = af;
}
/*
* Determine whether or not a port forward listens to loopback, the
* specified address or wildcard. On the client, a specified bind
* address will always override gateway_ports. On the server, a
* gateway_ports of 1 (``yes'') will override the client's specification
* and force a wildcard bind, whereas a value of 2 (``clientspecified'')
* will bind to whatever address the client asked for.
*
* Special-case listen_addrs are:
*
* "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
* "" (empty string), "*" -> wildcard v4/v6
* "localhost" -> loopback v4/v6
* "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set
*/
static const char *
-channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
+channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp,
int is_client, struct ForwardOptions *fwd_opts)
{
const char *addr = NULL;
int wildcard = 0;
if (listen_addr == NULL) {
/* No address specified: default to gateway_ports setting */
if (fwd_opts->gateway_ports)
wildcard = 1;
} else if (fwd_opts->gateway_ports || is_client) {
if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
(!is_client && fwd_opts->gateway_ports == 1)) {
wildcard = 1;
/*
* Notify client if they requested a specific listen
* address and it was overridden.
*/
if (*listen_addr != '\0' &&
strcmp(listen_addr, "0.0.0.0") != 0 &&
strcmp(listen_addr, "*") != 0) {
- packet_send_debug("Forwarding listen address "
+ ssh_packet_send_debug(ssh,
+ "Forwarding listen address "
"\"%s\" overridden by server "
"GatewayPorts", listen_addr);
}
} else if (strcmp(listen_addr, "localhost") != 0 ||
strcmp(listen_addr, "127.0.0.1") == 0 ||
strcmp(listen_addr, "::1") == 0) {
/* Accept localhost address when GatewayPorts=yes */
addr = listen_addr;
}
} else if (strcmp(listen_addr, "127.0.0.1") == 0 ||
strcmp(listen_addr, "::1") == 0) {
/*
* If a specific IPv4/IPv6 localhost address has been
* requested then accept it even if gateway_ports is in
* effect. This allows the client to prefer IPv4 or IPv6.
*/
addr = listen_addr;
}
if (wildcardp != NULL)
*wildcardp = wildcard;
return addr;
}
static int
channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
struct Forward *fwd, int *allocated_listen_port,
struct ForwardOptions *fwd_opts)
{
Channel *c;
int sock, r, success = 0, wildcard = 0, is_client;
struct addrinfo hints, *ai, *aitop;
const char *host, *addr;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
in_port_t *lport_p;
is_client = (type == SSH_CHANNEL_PORT_LISTENER);
if (is_client && fwd->connect_path != NULL) {
host = fwd->connect_path;
} else {
host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
fwd->listen_host : fwd->connect_host;
if (host == NULL) {
error("No forward host name.");
return 0;
}
if (strlen(host) >= NI_MAXHOST) {
error("Forward host name too long.");
return 0;
}
}
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */
- addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
+ addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard,
is_client, fwd_opts);
debug3("%s: type %d wildcard %d addr %s", __func__,
type, wildcard, (addr == NULL) ? "NULL" : addr);
/*
* getaddrinfo returns a loopback address if the hostname is
* set to NULL and hints.ai_flags is not AI_PASSIVE
*/
memset(&hints, 0, sizeof(hints));
hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_flags = wildcard ? AI_PASSIVE : 0;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", fwd->listen_port);
if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
if (addr == NULL) {
/* This really shouldn't happen */
- packet_disconnect("getaddrinfo: fatal error: %s",
+ ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s",
ssh_gai_strerror(r));
} else {
error("%s: getaddrinfo(%.64s): %s", __func__, addr,
ssh_gai_strerror(r));
}
return 0;
}
if (allocated_listen_port != NULL)
*allocated_listen_port = 0;
for (ai = aitop; ai; ai = ai->ai_next) {
switch (ai->ai_family) {
case AF_INET:
lport_p = &((struct sockaddr_in *)ai->ai_addr)->
sin_port;
break;
case AF_INET6:
lport_p = &((struct sockaddr_in6 *)ai->ai_addr)->
sin6_port;
break;
default:
continue;
}
/*
* If allocating a port for -R forwards, then use the
* same port for all address families.
*/
if (type == SSH_CHANNEL_RPORT_LISTENER &&
fwd->listen_port == 0 && allocated_listen_port != NULL &&
*allocated_listen_port > 0)
*lport_p = htons(*allocated_listen_port);
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("%s: getnameinfo failed", __func__);
continue;
}
/* Create a port to listen for the host. */
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0) {
/* this is no error since kernel may not support ipv6 */
verbose("socket [%s]:%s: %.100s", ntop, strport,
strerror(errno));
continue;
}
set_reuseaddr(sock);
if (ai->ai_family == AF_INET6)
sock_set_v6only(sock);
debug("Local forwarding listening on %s port %s.",
ntop, strport);
/* Bind the socket to the address. */
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
/*
* address can be in if use ipv6 address is
* already bound
*/
if (!ai->ai_next)
error("bind [%s]:%s: %.100s",
ntop, strport, strerror(errno));
else
verbose("bind [%s]:%s: %.100s",
ntop, strport, strerror(errno));
close(sock);
continue;
}
/* Start listening for connections on the socket. */
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
error("listen: %.100s", strerror(errno));
error("listen [%s]:%s: %.100s", ntop, strport,
strerror(errno));
close(sock);
continue;
}
/*
* fwd->listen_port == 0 requests a dynamically allocated port -
* record what we got.
*/
if (type == SSH_CHANNEL_RPORT_LISTENER &&
fwd->listen_port == 0 &&
allocated_listen_port != NULL &&
*allocated_listen_port == 0) {
*allocated_listen_port = get_local_port(sock);
debug("Allocated listen port %d",
*allocated_listen_port);
}
/* Allocate a channel number for the socket. */
c = channel_new(ssh, "port listener", type, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "port listener", 1);
c->path = xstrdup(host);
c->host_port = fwd->connect_port;
c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
!(datafellows & SSH_BUG_DYNAMIC_RPORT))
c->listening_port = *allocated_listen_port;
else
c->listening_port = fwd->listen_port;
success = 1;
}
if (success == 0)
error("%s: cannot listen to port: %d", __func__,
fwd->listen_port);
freeaddrinfo(aitop);
return success;
}
static int
channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type,
struct Forward *fwd, struct ForwardOptions *fwd_opts)
{
struct sockaddr_un sunaddr;
const char *path;
Channel *c;
int port, sock;
mode_t omask;
switch (type) {
case SSH_CHANNEL_UNIX_LISTENER:
if (fwd->connect_path != NULL) {
if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
error("Local connecting path too long: %s",
fwd->connect_path);
return 0;
}
path = fwd->connect_path;
port = PORT_STREAMLOCAL;
} else {
if (fwd->connect_host == NULL) {
error("No forward host name.");
return 0;
}
if (strlen(fwd->connect_host) >= NI_MAXHOST) {
error("Forward host name too long.");
return 0;
}
path = fwd->connect_host;
port = fwd->connect_port;
}
break;
case SSH_CHANNEL_RUNIX_LISTENER:
path = fwd->listen_path;
port = PORT_STREAMLOCAL;
break;
default:
error("%s: unexpected channel type %d", __func__, type);
return 0;
}
if (fwd->listen_path == NULL) {
error("No forward path name.");
return 0;
}
if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
error("Local listening path too long: %s", fwd->listen_path);
return 0;
}
debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
/* Start a Unix domain listener. */
omask = umask(fwd_opts->streamlocal_bind_mask);
sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
fwd_opts->streamlocal_bind_unlink);
umask(omask);
if (sock < 0)
return 0;
debug("Local forwarding listening on path %s.", fwd->listen_path);
/* Allocate a channel number for the socket. */
c = channel_new(ssh, "unix listener", type, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, "unix listener", 1);
c->path = xstrdup(path);
c->host_port = port;
c->listening_port = PORT_STREAMLOCAL;
c->listening_addr = xstrdup(fwd->listen_path);
return 1;
}
static int
channel_cancel_rport_listener_tcpip(struct ssh *ssh,
const char *host, u_short port)
{
u_int i;
int found = 0;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER)
continue;
if (strcmp(c->path, host) == 0 && c->listening_port == port) {
debug2("%s: close channel %d", __func__, i);
channel_free(ssh, c);
found = 1;
}
}
return found;
}
static int
channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path)
{
u_int i;
int found = 0;
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
continue;
if (c->path == NULL)
continue;
if (strcmp(c->path, path) == 0) {
debug2("%s: close channel %d", __func__, i);
channel_free(ssh, c);
found = 1;
}
}
return found;
}
int
channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd)
{
if (fwd->listen_path != NULL) {
return channel_cancel_rport_listener_streamlocal(ssh,
fwd->listen_path);
} else {
return channel_cancel_rport_listener_tcpip(ssh,
fwd->listen_host, fwd->listen_port);
}
}
static int
channel_cancel_lport_listener_tcpip(struct ssh *ssh,
const char *lhost, u_short lport, int cport,
struct ForwardOptions *fwd_opts)
{
u_int i;
int found = 0;
- const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
+ const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL, 1, fwd_opts);
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER)
continue;
if (c->listening_port != lport)
continue;
if (cport == CHANNEL_CANCEL_PORT_STATIC) {
/* skip dynamic forwardings */
if (c->host_port == 0)
continue;
} else {
if (c->host_port != cport)
continue;
}
if ((c->listening_addr == NULL && addr != NULL) ||
(c->listening_addr != NULL && addr == NULL))
continue;
if (addr == NULL || strcmp(c->listening_addr, addr) == 0) {
debug2("%s: close channel %d", __func__, i);
channel_free(ssh, c);
found = 1;
}
}
return found;
}
static int
channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path)
{
u_int i;
int found = 0;
if (path == NULL) {
error("%s: no path specified.", __func__);
return 0;
}
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
Channel *c = ssh->chanctxt->channels[i];
if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
continue;
if (c->listening_addr == NULL)
continue;
if (strcmp(c->listening_addr, path) == 0) {
debug2("%s: close channel %d", __func__, i);
channel_free(ssh, c);
found = 1;
}
}
return found;
}
int
channel_cancel_lport_listener(struct ssh *ssh,
struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
{
if (fwd->listen_path != NULL) {
return channel_cancel_lport_listener_streamlocal(ssh,
fwd->listen_path);
} else {
return channel_cancel_lport_listener_tcpip(ssh,
fwd->listen_host, fwd->listen_port, cport, fwd_opts);
}
}
/* protocol local port fwd, used by ssh */
int
channel_setup_local_fwd_listener(struct ssh *ssh,
struct Forward *fwd, struct ForwardOptions *fwd_opts)
{
if (fwd->listen_path != NULL) {
return channel_setup_fwd_listener_streamlocal(ssh,
SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
} else {
return channel_setup_fwd_listener_tcpip(ssh,
SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts);
}
}
/* Matches a remote forwarding permission against a requested forwarding */
static int
remote_open_match(struct permission *allowed_open, struct Forward *fwd)
{
int ret;
char *lhost;
/* XXX add ACLs for streamlocal */
if (fwd->listen_path != NULL)
return 1;
if (fwd->listen_host == NULL || allowed_open->listen_host == NULL)
return 0;
if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT &&
allowed_open->listen_port != fwd->listen_port)
return 0;
/* Match hostnames case-insensitively */
lhost = xstrdup(fwd->listen_host);
lowercase(lhost);
ret = match_pattern(lhost, allowed_open->listen_host);
free(lhost);
return ret;
}
/* Checks whether a requested remote forwarding is permitted */
static int
check_rfwd_permission(struct ssh *ssh, struct Forward *fwd)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->remote_perms;
u_int i, permit, permit_adm = 1;
struct permission *perm;
/* XXX apply GatewayPorts override before checking? */
permit = pset->all_permitted;
if (!permit) {
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (remote_open_match(perm, fwd)) {
permit = 1;
break;
}
}
}
if (pset->num_permitted_admin > 0) {
permit_adm = 0;
for (i = 0; i < pset->num_permitted_admin; i++) {
perm = &pset->permitted_admin[i];
if (remote_open_match(perm, fwd)) {
permit_adm = 1;
break;
}
}
}
return permit && permit_adm;
}
/* protocol v2 remote port fwd, used by sshd */
int
channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd,
int *allocated_listen_port, struct ForwardOptions *fwd_opts)
{
if (!check_rfwd_permission(ssh, fwd)) {
- packet_send_debug("port forwarding refused");
+ ssh_packet_send_debug(ssh, "port forwarding refused");
return 0;
}
if (fwd->listen_path != NULL) {
return channel_setup_fwd_listener_streamlocal(ssh,
SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
} else {
return channel_setup_fwd_listener_tcpip(ssh,
SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
fwd_opts);
}
}
/*
* Translate the requested rfwd listen host to something usable for
* this server.
*/
static const char *
channel_rfwd_bind_host(const char *listen_host)
{
if (listen_host == NULL) {
return "localhost";
} else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) {
return "";
} else
return listen_host;
}
/*
* Initiate forwarding of connections to port "port" on remote host through
* the secure channel to host:port from local side.
* Returns handle (index) for updating the dynamic listen port with
* channel_update_permission().
*/
int
channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
{
int r, success = 0, idx = -1;
char *host_to_connect, *listen_host, *listen_path;
int port_to_connect, listen_port;
/* Send the forward request to the remote side. */
if (fwd->listen_path != NULL) {
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh,
"streamlocal-forward@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
(r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: request streamlocal: %s",
__func__, ssh_err(r));
} else {
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 ||
(r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */
(r = sshpkt_put_cstring(ssh,
channel_rfwd_bind_host(fwd->listen_host))) != 0 ||
(r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: request tcpip-forward: %s",
__func__, ssh_err(r));
}
/* Assume that server accepts the request */
success = 1;
if (success) {
/* Record that connection to this host/port is permitted. */
host_to_connect = listen_host = listen_path = NULL;
port_to_connect = listen_port = 0;
if (fwd->connect_path != NULL) {
host_to_connect = xstrdup(fwd->connect_path);
port_to_connect = PORT_STREAMLOCAL;
} else {
host_to_connect = xstrdup(fwd->connect_host);
port_to_connect = fwd->connect_port;
}
if (fwd->listen_path != NULL) {
listen_path = xstrdup(fwd->listen_path);
listen_port = PORT_STREAMLOCAL;
} else {
if (fwd->listen_host != NULL)
listen_host = xstrdup(fwd->listen_host);
listen_port = fwd->listen_port;
}
idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL,
host_to_connect, port_to_connect,
listen_host, listen_path, listen_port, NULL);
}
return idx;
}
static int
open_match(struct permission *allowed_open, const char *requestedhost,
int requestedport)
{
if (allowed_open->host_to_connect == NULL)
return 0;
if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&
allowed_open->port_to_connect != requestedport)
return 0;
if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 &&
strcmp(allowed_open->host_to_connect, requestedhost) != 0)
return 0;
return 1;
}
/*
* Note that in the listen host/port case
* we don't support FWD_PERMIT_ANY_PORT and
* need to translate between the configured-host (listen_host)
* and what we've sent to the remote server (channel_rfwd_bind_host)
*/
static int
open_listen_match_tcpip(struct permission *allowed_open,
const char *requestedhost, u_short requestedport, int translate)
{
const char *allowed_host;
if (allowed_open->host_to_connect == NULL)
return 0;
if (allowed_open->listen_port != requestedport)
return 0;
if (!translate && allowed_open->listen_host == NULL &&
requestedhost == NULL)
return 1;
allowed_host = translate ?
channel_rfwd_bind_host(allowed_open->listen_host) :
allowed_open->listen_host;
if (allowed_host == NULL || requestedhost == NULL ||
strcmp(allowed_host, requestedhost) != 0)
return 0;
return 1;
}
static int
open_listen_match_streamlocal(struct permission *allowed_open,
const char *requestedpath)
{
if (allowed_open->host_to_connect == NULL)
return 0;
if (allowed_open->listen_port != PORT_STREAMLOCAL)
return 0;
if (allowed_open->listen_path == NULL ||
strcmp(allowed_open->listen_path, requestedpath) != 0)
return 0;
return 1;
}
/*
* Request cancellation of remote forwarding of connection host:port from
* local side.
*/
static int
channel_request_rforward_cancel_tcpip(struct ssh *ssh,
const char *host, u_short port)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
int r;
u_int i;
struct permission *perm;
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (open_listen_match_tcpip(perm, host, port, 0))
break;
perm = NULL;
}
if (perm == NULL) {
debug("%s: requested forward not found", __func__);
return -1;
}
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
(r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 ||
(r = sshpkt_put_u32(ssh, port)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: send cancel: %s", __func__, ssh_err(r));
fwd_perm_clear(perm); /* unregister */
return 0;
}
/*
* Request cancellation of remote forwarding of Unix domain socket
* path from local side.
*/
static int
channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
int r;
u_int i;
struct permission *perm;
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (open_listen_match_streamlocal(perm, path))
break;
perm = NULL;
}
if (perm == NULL) {
debug("%s: requested forward not found", __func__);
return -1;
}
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh,
"cancel-streamlocal-forward@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
(r = sshpkt_put_cstring(ssh, path)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: send cancel: %s", __func__, ssh_err(r));
fwd_perm_clear(perm); /* unregister */
return 0;
}
/*
* Request cancellation of remote forwarding of a connection from local side.
*/
int
channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd)
{
if (fwd->listen_path != NULL) {
return channel_request_rforward_cancel_streamlocal(ssh,
fwd->listen_path);
} else {
return channel_request_rforward_cancel_tcpip(ssh,
fwd->listen_host,
fwd->listen_port ? fwd->listen_port : fwd->allocated_port);
}
}
/*
* Permits opening to any host/port if permitted_user[] is empty. This is
* usually called by the server, because the user could connect to any port
* anyway, and the server has no way to know but to trust the client anyway.
*/
void
channel_permit_all(struct ssh *ssh, int where)
{
struct permission_set *pset = permission_set_get(ssh, where);
if (pset->num_permitted_user == 0)
pset->all_permitted = 1;
}
/*
* Permit the specified host/port for forwarding.
*/
void
channel_add_permission(struct ssh *ssh, int who, int where,
char *host, int port)
{
int local = where == FORWARD_LOCAL;
struct permission_set *pset = permission_set_get(ssh, where);
debug("allow %s forwarding to host %s port %d",
fwd_ident(who, where), host, port);
/*
* Remote forwards set listen_host/port, local forwards set
* host/port_to_connect.
*/
permission_set_add(ssh, who, where,
local ? host : 0, local ? port : 0,
local ? NULL : host, NULL, local ? 0 : port, NULL);
pset->all_permitted = 0;
}
/*
* Administratively disable forwarding.
*/
void
channel_disable_admin(struct ssh *ssh, int where)
{
channel_clear_permission(ssh, FORWARD_ADM, where);
permission_set_add(ssh, FORWARD_ADM, where,
NULL, 0, NULL, NULL, 0, NULL);
}
/*
* Clear a list of permitted opens.
*/
void
channel_clear_permission(struct ssh *ssh, int who, int where)
{
struct permission **permp;
u_int *npermp;
permission_set_get_array(ssh, who, where, &permp, &npermp);
*permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp));
*npermp = 0;
}
/*
* Update the listen port for a dynamic remote forward, after
* the actual 'newport' has been allocated. If 'newport' < 0 is
* passed then they entry will be invalidated.
*/
void
channel_update_permission(struct ssh *ssh, int idx, int newport)
{
struct permission_set *pset = &ssh->chanctxt->local_perms;
if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
debug("%s: index out of range: %d num_permitted_user %d",
__func__, idx, pset->num_permitted_user);
return;
}
debug("%s allowed port %d for forwarding to host %s port %d",
newport > 0 ? "Updating" : "Removing",
newport,
pset->permitted_user[idx].host_to_connect,
pset->permitted_user[idx].port_to_connect);
if (newport <= 0)
fwd_perm_clear(&pset->permitted_user[idx]);
else {
pset->permitted_user[idx].listen_port =
(datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
}
}
/* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */
int
permitopen_port(const char *p)
{
int port;
if (strcmp(p, "*") == 0)
return FWD_PERMIT_ANY_PORT;
if ((port = a2port(p)) > 0)
return port;
return -1;
}
/* Try to start non-blocking connect to next host in cctx list */
static int
connect_next(struct channel_connect *cctx)
{
int sock, saved_errno;
struct sockaddr_un *sunaddr;
char ntop[NI_MAXHOST];
char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))];
for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
switch (cctx->ai->ai_family) {
case AF_UNIX:
/* unix:pathname instead of host:port */
sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
strlcpy(ntop, "unix", sizeof(ntop));
strlcpy(strport, sunaddr->sun_path, sizeof(strport));
break;
case AF_INET:
case AF_INET6:
if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
error("connect_next: getnameinfo failed");
continue;
}
break;
default:
continue;
}
if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
cctx->ai->ai_protocol)) == -1) {
if (cctx->ai->ai_next == NULL)
error("socket: %.100s", strerror(errno));
else
verbose("socket: %.100s", strerror(errno));
continue;
}
if (set_nonblock(sock) == -1)
fatal("%s: set_nonblock(%d)", __func__, sock);
if (connect(sock, cctx->ai->ai_addr,
cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
debug("connect_next: host %.100s ([%.100s]:%s): "
"%.100s", cctx->host, ntop, strport,
strerror(errno));
saved_errno = errno;
close(sock);
errno = saved_errno;
continue; /* fail -- try next */
}
if (cctx->ai->ai_family != AF_UNIX)
set_nodelay(sock);
debug("connect_next: host %.100s ([%.100s]:%s) "
"in progress, fd=%d", cctx->host, ntop, strport, sock);
cctx->ai = cctx->ai->ai_next;
return sock;
}
return -1;
}
static void
channel_connect_ctx_free(struct channel_connect *cctx)
{
free(cctx->host);
if (cctx->aitop) {
if (cctx->aitop->ai_family == AF_UNIX)
free(cctx->aitop);
else
freeaddrinfo(cctx->aitop);
}
memset(cctx, 0, sizeof(*cctx));
}
/*
* Return connecting socket to remote host:port or local socket path,
* passing back the failure reason if appropriate.
*/
static int
connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype,
char *ctype, char *rname, struct channel_connect *cctx,
int *reason, const char **errmsg)
{
struct addrinfo hints;
int gaierr;
int sock = -1;
char strport[NI_MAXSERV];
if (port == PORT_STREAMLOCAL) {
struct sockaddr_un *sunaddr;
struct addrinfo *ai;
if (strlen(name) > sizeof(sunaddr->sun_path)) {
error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
return -1;
}
/*
* Fake up a struct addrinfo for AF_UNIX connections.
* channel_connect_ctx_free() must check ai_family
* and use free() not freeaddirinfo() for AF_UNIX.
*/
ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
ai->ai_addr = (struct sockaddr *)(ai + 1);
ai->ai_addrlen = sizeof(*sunaddr);
ai->ai_family = AF_UNIX;
ai->ai_socktype = socktype;
ai->ai_protocol = PF_UNSPEC;
sunaddr = (struct sockaddr_un *)ai->ai_addr;
sunaddr->sun_family = AF_UNIX;
strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
cctx->aitop = ai;
} else {
memset(&hints, 0, sizeof(hints));
hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_socktype = socktype;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop))
!= 0) {
if (errmsg != NULL)
*errmsg = ssh_gai_strerror(gaierr);
if (reason != NULL)
*reason = SSH2_OPEN_CONNECT_FAILED;
error("connect_to %.100s: unknown host (%s)", name,
ssh_gai_strerror(gaierr));
return -1;
}
}
cctx->host = xstrdup(name);
cctx->port = port;
cctx->ai = cctx->aitop;
if ((sock = connect_next(cctx)) == -1) {
error("connect to %.100s port %d failed: %s",
name, port, strerror(errno));
return -1;
}
return sock;
}
/* Return CONNECTING channel to remote host:port or local socket path */
static Channel *
connect_to(struct ssh *ssh, const char *host, int port,
char *ctype, char *rname)
{
struct channel_connect cctx;
Channel *c;
int sock;
memset(&cctx, 0, sizeof(cctx));
sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname,
&cctx, NULL, NULL);
if (sock == -1) {
channel_connect_ctx_free(&cctx);
return NULL;
}
c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
c->host_port = port;
c->path = xstrdup(host);
c->connect_ctx = cctx;
return c;
}
/*
* returns either the newly connected channel or the downstream channel
* that needs to deal with this connection.
*/
Channel *
channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host,
u_short listen_port, char *ctype, char *rname)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
u_int i;
struct permission *perm;
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (open_listen_match_tcpip(perm,
listen_host, listen_port, 1)) {
if (perm->downstream)
return perm->downstream;
if (perm->port_to_connect == 0)
return rdynamic_connect_prepare(ssh,
ctype, rname);
return connect_to(ssh,
perm->host_to_connect, perm->port_to_connect,
ctype, rname);
}
}
error("WARNING: Server requests forwarding for unknown listen_port %d",
listen_port);
return NULL;
}
Channel *
channel_connect_by_listen_path(struct ssh *ssh, const char *path,
char *ctype, char *rname)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
u_int i;
struct permission *perm;
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (open_listen_match_streamlocal(perm, path)) {
return connect_to(ssh,
perm->host_to_connect, perm->port_to_connect,
ctype, rname);
}
}
error("WARNING: Server requests forwarding for unknown path %.100s",
path);
return NULL;
}
/* Check if connecting to that port is permitted and connect. */
Channel *
channel_connect_to_port(struct ssh *ssh, const char *host, u_short port,
char *ctype, char *rname, int *reason, const char **errmsg)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
struct channel_connect cctx;
Channel *c;
u_int i, permit, permit_adm = 1;
int sock;
struct permission *perm;
permit = pset->all_permitted;
if (!permit) {
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (open_match(perm, host, port)) {
permit = 1;
break;
}
}
}
if (pset->num_permitted_admin > 0) {
permit_adm = 0;
for (i = 0; i < pset->num_permitted_admin; i++) {
perm = &pset->permitted_admin[i];
if (open_match(perm, host, port)) {
permit_adm = 1;
break;
}
}
}
if (!permit || !permit_adm) {
logit("Received request to connect to host %.100s port %d, "
"but the request was denied.", host, port);
if (reason != NULL)
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
return NULL;
}
memset(&cctx, 0, sizeof(cctx));
sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname,
&cctx, reason, errmsg);
if (sock == -1) {
channel_connect_ctx_free(&cctx);
return NULL;
}
c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
c->host_port = port;
c->path = xstrdup(host);
c->connect_ctx = cctx;
return c;
}
/* Check if connecting to that path is permitted and connect. */
Channel *
channel_connect_to_path(struct ssh *ssh, const char *path,
char *ctype, char *rname)
{
struct ssh_channels *sc = ssh->chanctxt;
struct permission_set *pset = &sc->local_perms;
u_int i, permit, permit_adm = 1;
struct permission *perm;
permit = pset->all_permitted;
if (!permit) {
for (i = 0; i < pset->num_permitted_user; i++) {
perm = &pset->permitted_user[i];
if (open_match(perm, path, PORT_STREAMLOCAL)) {
permit = 1;
break;
}
}
}
if (pset->num_permitted_admin > 0) {
permit_adm = 0;
for (i = 0; i < pset->num_permitted_admin; i++) {
perm = &pset->permitted_admin[i];
if (open_match(perm, path, PORT_STREAMLOCAL)) {
permit_adm = 1;
break;
}
}
}
if (!permit || !permit_adm) {
logit("Received request to connect to path %.100s, "
"but the request was denied.", path);
return NULL;
}
return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname);
}
void
channel_send_window_changes(struct ssh *ssh)
{
struct ssh_channels *sc = ssh->chanctxt;
struct winsize ws;
int r;
u_int i;
for (i = 0; i < sc->channels_alloc; i++) {
if (sc->channels[i] == NULL || !sc->channels[i]->client_tty ||
sc->channels[i]->type != SSH_CHANNEL_OPEN)
continue;
if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
continue;
channel_request_start(ssh, i, "window-change", 0);
if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: channel %u: send window-change: %s",
__func__, i, ssh_err(r));
}
}
/* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */
static Channel *
rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
{
Channel *c;
int r;
c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
c->host_port = 0;
c->path = NULL;
/*
* We need to open the channel before we have a FD,
* so that we can get SOCKS header from peer.
*/
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->self)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
fatal("%s: channel %i: confirm: %s", __func__,
c->self, ssh_err(r));
}
return c;
}
/* Return CONNECTING socket to remote host:port or local socket path */
static int
rdynamic_connect_finish(struct ssh *ssh, Channel *c)
{
struct channel_connect cctx;
int sock;
memset(&cctx, 0, sizeof(cctx));
sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL,
NULL, &cctx, NULL, NULL);
if (sock == -1)
channel_connect_ctx_free(&cctx);
else {
/* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */
c->type = SSH_CHANNEL_RDYNAMIC_FINISH;
c->connect_ctx = cctx;
channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0);
}
return sock;
}
/* -- X11 forwarding */
/*
* Creates an internet domain socket for listening for X11 connections.
* Returns 0 and a suitable display number for the DISPLAY variable
* stored in display_numberp , or -1 if an error occurs.
*/
int
x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
int x11_use_localhost, int single_connection,
u_int *display_numberp, int **chanids)
{
Channel *nc = NULL;
int display_number, sock;
u_short port;
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
if (chanids == NULL)
return -1;
for (display_number = x11_display_offset;
display_number < MAX_DISPLAYS;
display_number++) {
port = 6000 + display_number;
memset(&hints, 0, sizeof(hints));
hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(NULL, strport,
&hints, &aitop)) != 0) {
error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET &&
ai->ai_family != AF_INET6)
continue;
sock = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (sock < 0) {
if ((errno != EINVAL) && (errno != EAFNOSUPPORT)
#ifdef EPFNOSUPPORT
&& (errno != EPFNOSUPPORT)
#endif
) {
error("socket: %.100s", strerror(errno));
freeaddrinfo(aitop);
return -1;
} else {
debug("x11_create_display_inet: Socket family %d not supported",
ai->ai_family);
continue;
}
}
if (ai->ai_family == AF_INET6)
sock_set_v6only(sock);
if (x11_use_localhost)
set_reuseaddr(sock);
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
debug2("%s: bind port %d: %.100s", __func__,
port, strerror(errno));
close(sock);
for (n = 0; n < num_socks; n++)
close(socks[n]);
num_socks = 0;
break;
}
socks[num_socks++] = sock;
if (num_socks == NUM_SOCKS)
break;
}
freeaddrinfo(aitop);
if (num_socks > 0)
break;
}
if (display_number >= MAX_DISPLAYS) {
error("Failed to allocate internet-domain X11 display socket.");
return -1;
}
/* Start listening for connections on the socket. */
for (n = 0; n < num_socks; n++) {
sock = socks[n];
if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
error("listen: %.100s", strerror(errno));
close(sock);
return -1;
}
}
/* Allocate a channel for each socket. */
*chanids = xcalloc(num_socks + 1, sizeof(**chanids));
for (n = 0; n < num_socks; n++) {
sock = socks[n];
nc = channel_new(ssh, "x11 listener",
SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, "X11 inet listener", 1);
nc->single_connection = single_connection;
(*chanids)[n] = nc->self;
}
(*chanids)[n] = -1;
/* Return the display number for the DISPLAY environment variable. */
*display_numberp = display_number;
return 0;
}
static int
connect_local_xsocket_path(const char *pathname)
{
int sock;
struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
error("socket: %.100s", strerror(errno));
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strlcpy(addr.sun_path, pathname, sizeof addr.sun_path);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
return sock;
close(sock);
error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
return -1;
}
static int
connect_local_xsocket(u_int dnr)
{
char buf[1024];
snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr);
return connect_local_xsocket_path(buf);
}
#ifdef __APPLE__
static int
is_path_to_xsocket(const char *display, char *path, size_t pathlen)
{
struct stat sbuf;
if (strlcpy(path, display, pathlen) >= pathlen) {
error("%s: display path too long", __func__);
return 0;
}
if (display[0] != '/')
return 0;
if (stat(path, &sbuf) == 0) {
return 1;
} else {
char *dot = strrchr(path, '.');
if (dot != NULL) {
*dot = '\0';
if (stat(path, &sbuf) == 0) {
return 1;
}
}
}
return 0;
}
#endif
int
x11_connect_display(struct ssh *ssh)
{
u_int display_number;
const char *display;
char buf[1024], *cp;
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr, sock = 0;
/* Try to open a socket for the local X server. */
display = getenv("DISPLAY");
if (!display) {
error("DISPLAY not set.");
return -1;
}
/*
* Now we decode the value of the DISPLAY variable and make a
* connection to the real X server.
*/
#ifdef __APPLE__
/* Check if display is a path to a socket (as set by launchd). */
{
char path[PATH_MAX];
if (is_path_to_xsocket(display, path, sizeof(path))) {
debug("x11_connect_display: $DISPLAY is launchd");
/* Create a socket. */
sock = connect_local_xsocket_path(path);
if (sock < 0)
return -1;
/* OK, we now have a connection to the display. */
return sock;
}
}
#endif
/*
* Check if it is a unix domain socket. Unix domain displays are in
* one of the following formats: unix:d[.s], :d[.s], ::d[.s]
*/
if (strncmp(display, "unix:", 5) == 0 ||
display[0] == ':') {
/* Connect to the unix domain socket. */
if (sscanf(strrchr(display, ':') + 1, "%u",
&display_number) != 1) {
error("Could not parse display number from DISPLAY: "
"%.100s", display);
return -1;
}
/* Create a socket. */
sock = connect_local_xsocket(display_number);
if (sock < 0)
return -1;
/* OK, we now have a connection to the display. */
return sock;
}
/*
* Connect to an inet socket. The DISPLAY value is supposedly
* hostname:d[.s], where hostname may also be numeric IP address.
*/
strlcpy(buf, display, sizeof(buf));
cp = strchr(buf, ':');
if (!cp) {
error("Could not find ':' in DISPLAY: %.100s", display);
return -1;
}
*cp = 0;
/*
* buf now contains the host name. But first we parse the
* display number.
*/
if (sscanf(cp + 1, "%u", &display_number) != 1) {
error("Could not parse display number from DISPLAY: %.100s",
display);
return -1;
}
/* Look up the host address */
memset(&hints, 0, sizeof(hints));
hints.ai_family = ssh->chanctxt->IPv4or6;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%u", 6000 + display_number);
if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
error("%.100s: unknown host. (%s)", buf,
ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
/* Create a socket. */
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0) {
debug2("socket: %.100s", strerror(errno));
continue;
}
/* Connect it to the display. */
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
debug2("connect %.100s port %u: %.100s", buf,
6000 + display_number, strerror(errno));
close(sock);
continue;
}
/* Success */
break;
}
freeaddrinfo(aitop);
if (!ai) {
error("connect %.100s port %u: %.100s", buf,
6000 + display_number, strerror(errno));
return -1;
}
set_nodelay(sock);
return sock;
}
/*
* Requests forwarding of X11 connections, generates fake authentication
* data, and enables authentication spoofing.
* This should be called in the client only.
*/
void
x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id,
const char *disp, const char *proto, const char *data, int want_reply)
{
struct ssh_channels *sc = ssh->chanctxt;
u_int data_len = (u_int) strlen(data) / 2;
u_int i, value;
const char *cp;
char *new_data;
int r, screen_number;
if (sc->x11_saved_display == NULL)
sc->x11_saved_display = xstrdup(disp);
else if (strcmp(disp, sc->x11_saved_display) != 0) {
error("x11_request_forwarding_with_spoofing: different "
"$DISPLAY already forwarded");
return;
}
cp = strchr(disp, ':');
if (cp)
cp = strchr(cp, '.');
if (cp)
screen_number = (u_int)strtonum(cp + 1, 0, 400, NULL);
else
screen_number = 0;
if (sc->x11_saved_proto == NULL) {
/* Save protocol name. */
sc->x11_saved_proto = xstrdup(proto);
/* Extract real authentication data. */
sc->x11_saved_data = xmalloc(data_len);
for (i = 0; i < data_len; i++) {
if (sscanf(data + 2 * i, "%2x", &value) != 1)
fatal("x11_request_forwarding: bad "
"authentication data: %.100s", data);
sc->x11_saved_data[i] = value;
}
sc->x11_saved_data_len = data_len;
/* Generate fake data of the same length. */
sc->x11_fake_data = xmalloc(data_len);
arc4random_buf(sc->x11_fake_data, data_len);
sc->x11_fake_data_len = data_len;
}
/* Convert the fake data into hex. */
new_data = tohex(sc->x11_fake_data, data_len);
/* Send the request packet. */
channel_request_start(ssh, client_session_id, "x11-req", want_reply);
if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */
(r = sshpkt_put_cstring(ssh, proto)) != 0 ||
(r = sshpkt_put_cstring(ssh, new_data)) != 0 ||
(r = sshpkt_put_u32(ssh, screen_number)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: send x11-req: %s", __func__, ssh_err(r));
free(new_data);
}
diff --git a/clientloop.c b/clientloop.c
index 8d312cdaa755..086c0dfe8e6b 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,2358 +1,2407 @@
-/* $OpenBSD: clientloop.c,v 1.318 2018/09/21 12:46:22 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.322 2019/03/29 11:31:40 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* The main loop for the interactive session (client side).
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* Copyright (c) 1999 Theo de Raadt. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* SSH2 support added by Markus Friedl.
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/socket.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <pwd.h>
#include <unistd.h>
#include <limits.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "packet.h"
#include "sshbuf.h"
#include "compat.h"
#include "channels.h"
#include "dispatch.h"
#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "myproposal.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "clientloop.h"
#include "sshconnect.h"
#include "authfd.h"
#include "atomicio.h"
#include "sshpty.h"
#include "match.h"
#include "msg.h"
#include "ssherr.h"
#include "hostfile.h"
/* import options */
extern Options options;
/* Flag indicating that stdin should be redirected from /dev/null. */
extern int stdin_null_flag;
/* Flag indicating that no shell has been requested */
extern int no_shell_flag;
/* Flag indicating that ssh should daemonise after authentication is complete */
extern int fork_after_authentication_flag;
/* Control socket */
extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
/*
* Name of the host we are connecting to. This is the name given on the
* command line, or the HostName specified for the user-supplied name in a
* configuration file.
*/
extern char *host;
/*
* Flag to indicate that we have received a window change signal which has
* not yet been processed. This will cause a message indicating the new
* window size to be sent to the server a little later. This is volatile
* because this is updated in a signal handler.
*/
static volatile sig_atomic_t received_window_change_signal = 0;
static volatile sig_atomic_t received_signal = 0;
/* Flag indicating whether the user's terminal is in non-blocking mode. */
static int in_non_blocking_mode = 0;
/* Time when backgrounded control master using ControlPersist should exit */
static time_t control_persist_exit_time = 0;
/* Common data for the client loop code. */
volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
static int last_was_cr; /* Last character was a newline. */
static int exit_status; /* Used to store the command exit status. */
static struct sshbuf *stderr_buffer; /* Used for final exit message. */
static int connection_in; /* Connection to server (input). */
static int connection_out; /* Connection to server (output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
static int session_closed; /* In SSH2: login session closed. */
static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
-static void client_init_dispatch(void);
+static void client_init_dispatch(struct ssh *ssh);
int session_ident = -1;
/* Track escape per proto2 channel */
struct escape_filter_ctx {
int escape_pending;
int escape_char;
};
/* Context for channel confirmation replies */
struct channel_reply_ctx {
const char *request_type;
int id;
enum confirm_action action;
};
/* Global request success/failure callbacks */
/* XXX move to struct ssh? */
struct global_confirm {
TAILQ_ENTRY(global_confirm) entry;
global_confirm_cb *cb;
void *ctx;
int ref_count;
};
TAILQ_HEAD(global_confirms, global_confirm);
static struct global_confirms global_confirms =
TAILQ_HEAD_INITIALIZER(global_confirms);
void ssh_process_session2_setup(int, int, int, struct sshbuf *);
/* Restores stdin to blocking mode. */
static void
leave_non_blocking(void)
{
if (in_non_blocking_mode) {
unset_nonblock(fileno(stdin));
in_non_blocking_mode = 0;
}
}
/*
* Signal handler for the window change signal (SIGWINCH). This just sets a
* flag indicating that the window has changed.
*/
/*ARGSUSED */
static void
window_change_handler(int sig)
{
received_window_change_signal = 1;
}
/*
* Signal handler for signals that cause the program to terminate. These
* signals must be trapped to restore terminal modes.
*/
/*ARGSUSED */
static void
signal_handler(int sig)
{
received_signal = sig;
quit_pending = 1;
}
/*
* Sets control_persist_exit_time to the absolute time when the
* backgrounded control master should exit due to expiry of the
* ControlPersist timeout. Sets it to 0 if we are not a backgrounded
* control master process, or if there is no ControlPersist timeout.
*/
static void
set_control_persist_exit_time(struct ssh *ssh)
{
if (muxserver_sock == -1 || !options.control_persist
|| options.control_persist_timeout == 0) {
/* not using a ControlPersist timeout */
control_persist_exit_time = 0;
} else if (channel_still_open(ssh)) {
/* some client connections are still open */
if (control_persist_exit_time > 0)
debug2("%s: cancel scheduled exit", __func__);
control_persist_exit_time = 0;
} else if (control_persist_exit_time <= 0) {
/* a client connection has recently closed */
control_persist_exit_time = monotime() +
(time_t)options.control_persist_timeout;
debug2("%s: schedule exit in %d seconds", __func__,
options.control_persist_timeout);
}
/* else we are already counting down to the timeout */
}
#define SSH_X11_VALID_DISPLAY_CHARS ":/.-_"
static int
client_x11_display_valid(const char *display)
{
size_t i, dlen;
if (display == NULL)
return 0;
dlen = strlen(display);
for (i = 0; i < dlen; i++) {
if (!isalnum((u_char)display[i]) &&
strchr(SSH_X11_VALID_DISPLAY_CHARS, display[i]) == NULL) {
debug("Invalid character '%c' in DISPLAY", display[i]);
return 0;
}
}
return 1;
}
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
#define X11_TIMEOUT_SLACK 60
int
client_x11_get_proto(struct ssh *ssh, const char *display,
const char *xauth_path, u_int trusted, u_int timeout,
char **_proto, char **_data)
{
char *cmd, line[512], xdisplay[512];
char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
static char proto[512], data[512];
FILE *f;
int got_data = 0, generated = 0, do_unlink = 0, r;
struct stat st;
u_int now, x11_timeout_real;
*_proto = proto;
*_data = data;
proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0';
if (!client_x11_display_valid(display)) {
if (display != NULL)
logit("DISPLAY \"%s\" invalid; disabling X11 forwarding",
display);
return -1;
}
if (xauth_path != NULL && stat(xauth_path, &st) == -1) {
debug("No xauth program.");
xauth_path = NULL;
}
if (xauth_path != NULL) {
/*
* Handle FamilyLocal case where $DISPLAY does
* not match an authorization entry. For this we
* just try "xauth list unix:displaynum.screennum".
* XXX: "localhost" match to determine FamilyLocal
* is not perfect.
*/
if (strncmp(display, "localhost:", 10) == 0) {
if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
display + 10)) < 0 ||
(size_t)r >= sizeof(xdisplay)) {
error("%s: display name too long", __func__);
return -1;
}
display = xdisplay;
}
if (trusted == 0) {
/*
* Generate an untrusted X11 auth cookie.
*
* The authentication cookie should briefly outlive
* ssh's willingness to forward X11 connections to
* avoid nasty fail-open behaviour in the X server.
*/
mktemp_proto(xauthdir, sizeof(xauthdir));
if (mkdtemp(xauthdir) == NULL) {
error("%s: mkdtemp: %s",
__func__, strerror(errno));
return -1;
}
do_unlink = 1;
if ((r = snprintf(xauthfile, sizeof(xauthfile),
"%s/xauthfile", xauthdir)) < 0 ||
(size_t)r >= sizeof(xauthfile)) {
error("%s: xauthfile path too long", __func__);
unlink(xauthfile);
rmdir(xauthdir);
return -1;
}
if (timeout == 0) {
/* auth doesn't time out */
xasprintf(&cmd, "%s -f %s generate %s %s "
"untrusted 2>%s",
xauth_path, xauthfile, display,
SSH_X11_PROTO, _PATH_DEVNULL);
} else {
/* Add some slack to requested expiry */
if (timeout < UINT_MAX - X11_TIMEOUT_SLACK)
x11_timeout_real = timeout +
X11_TIMEOUT_SLACK;
else {
/* Don't overflow on long timeouts */
x11_timeout_real = UINT_MAX;
}
xasprintf(&cmd, "%s -f %s generate %s %s "
"untrusted timeout %u 2>%s",
xauth_path, xauthfile, display,
SSH_X11_PROTO, x11_timeout_real,
_PATH_DEVNULL);
}
- debug2("%s: %s", __func__, cmd);
+ debug2("%s: xauth command: %s", __func__, cmd);
if (timeout != 0 && x11_refuse_time == 0) {
now = monotime() + 1;
if (UINT_MAX - timeout < now)
x11_refuse_time = UINT_MAX;
else
x11_refuse_time = now + timeout;
channel_set_x11_refuse_time(ssh,
x11_refuse_time);
}
if (system(cmd) == 0)
generated = 1;
free(cmd);
}
/*
* When in untrusted mode, we read the cookie only if it was
* successfully generated as an untrusted one in the step
* above.
*/
if (trusted || generated) {
xasprintf(&cmd,
"%s %s%s list %s 2>" _PATH_DEVNULL,
xauth_path,
generated ? "-f " : "" ,
generated ? xauthfile : "",
display);
debug2("x11_get_proto: %s", cmd);
f = popen(cmd, "r");
if (f && fgets(line, sizeof(line), f) &&
sscanf(line, "%*s %511s %511s", proto, data) == 2)
got_data = 1;
if (f)
pclose(f);
free(cmd);
}
}
if (do_unlink) {
unlink(xauthfile);
rmdir(xauthdir);
}
/* Don't fall back to fake X11 data for untrusted forwarding */
if (!trusted && !got_data) {
error("Warning: untrusted X11 forwarding setup failed: "
"xauth key data not generated");
return -1;
}
/*
* If we didn't get authentication data, just make up some
* data. The forwarding code will check the validity of the
* response anyway, and substitute this data. The X11
* server, however, will ignore this fake data and use
* whatever authentication mechanisms it was using otherwise
* for the local connection.
*/
if (!got_data) {
u_int8_t rnd[16];
u_int i;
logit("Warning: No xauth data; "
"using fake authentication data for X11 forwarding.");
strlcpy(proto, SSH_X11_PROTO, sizeof proto);
arc4random_buf(rnd, sizeof(rnd));
for (i = 0; i < sizeof(rnd); i++) {
snprintf(data + 2 * i, sizeof data - 2 * i, "%02x",
rnd[i]);
}
}
return 0;
}
/*
* Checks if the client window has changed, and sends a packet about it to
* the server if so. The actual change is detected elsewhere (by a software
* interrupt on Unix); this just checks the flag and sends a message if
* appropriate.
*/
static void
client_check_window_change(struct ssh *ssh)
{
if (!received_window_change_signal)
return;
/** XXX race */
received_window_change_signal = 0;
debug2("%s: changed", __func__);
channel_send_window_changes(ssh);
}
static int
client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
{
struct global_confirm *gc;
if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
return 0;
if (gc->cb != NULL)
gc->cb(ssh, type, seq, gc->ctx);
if (--gc->ref_count <= 0) {
TAILQ_REMOVE(&global_confirms, gc, entry);
explicit_bzero(gc, sizeof(*gc));
free(gc);
}
- packet_set_alive_timeouts(0);
+ ssh_packet_set_alive_timeouts(ssh, 0);
return 0;
}
static void
-server_alive_check(void)
+server_alive_check(struct ssh *ssh)
{
- if (packet_inc_alive_timeouts() > options.server_alive_count_max) {
+ int r;
+
+ if (ssh_packet_inc_alive_timeouts(ssh) > options.server_alive_count_max) {
logit("Timeout, server %s not responding.", host);
cleanup_exit(255);
}
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("keepalive@openssh.com");
- packet_put_char(1); /* boolean: want reply */
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send packet: %s", __func__, ssh_err(r));
/* Insert an empty placeholder to maintain ordering */
client_register_global_confirm(NULL, NULL);
}
/*
* Waits until the client can do something (some data becomes available on
* one of the file descriptors).
*/
static void
client_wait_until_can_do_something(struct ssh *ssh,
fd_set **readsetp, fd_set **writesetp,
int *maxfdp, u_int *nallocp, int rekeying)
{
struct timeval tv, *tvp;
int timeout_secs;
time_t minwait_secs = 0, server_alive_time = 0, now = monotime();
int r, ret;
/* Add any selections by the channel mechanism. */
- channel_prepare_select(active_state, readsetp, writesetp, maxfdp,
+ channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
nallocp, &minwait_secs);
/* channel_prepare_select could have closed the last channel */
if (session_closed && !channel_still_open(ssh) &&
- !packet_have_data_to_write()) {
+ !ssh_packet_have_data_to_write(ssh)) {
/* clear mask since we did not call select() */
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
return;
}
FD_SET(connection_in, *readsetp);
/* Select server connection if have data to write to the server. */
- if (packet_have_data_to_write())
+ if (ssh_packet_have_data_to_write(ssh))
FD_SET(connection_out, *writesetp);
/*
* Wait for something to happen. This will suspend the process until
* some selected descriptor can be read, written, or has some other
* event pending, or a timeout expires.
*/
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
if (options.server_alive_interval > 0) {
timeout_secs = options.server_alive_interval;
server_alive_time = now + options.server_alive_interval;
}
if (options.rekey_interval > 0 && !rekeying)
- timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout());
+ timeout_secs = MINIMUM(timeout_secs,
+ ssh_packet_get_rekey_timeout(ssh));
set_control_persist_exit_time(ssh);
if (control_persist_exit_time > 0) {
timeout_secs = MINIMUM(timeout_secs,
control_persist_exit_time - now);
if (timeout_secs < 0)
timeout_secs = 0;
}
if (minwait_secs != 0)
timeout_secs = MINIMUM(timeout_secs, (int)minwait_secs);
if (timeout_secs == INT_MAX)
tvp = NULL;
else {
tv.tv_sec = timeout_secs;
tv.tv_usec = 0;
tvp = &tv;
}
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
if (ret < 0) {
/*
* We have to clear the select masks, because we return.
* We have to return, because the mainloop checks for the flags
* set by the signal handlers.
*/
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
if (errno == EINTR)
return;
/* Note: we might still have data in the buffers. */
if ((r = sshbuf_putf(stderr_buffer,
"select: %s\r\n", strerror(errno))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
quit_pending = 1;
} else if (ret == 0) {
/*
* Timeout. Could have been either keepalive or rekeying.
* Keepalive we check here, rekeying is checked in clientloop.
*/
if (server_alive_time != 0 && server_alive_time <= monotime())
- server_alive_check();
+ server_alive_check(ssh);
}
}
static void
client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr)
{
/* Flush stdout and stderr buffers. */
if (sshbuf_len(bout) > 0)
atomicio(vwrite, fileno(stdout), sshbuf_mutable_ptr(bout),
sshbuf_len(bout));
if (sshbuf_len(berr) > 0)
atomicio(vwrite, fileno(stderr), sshbuf_mutable_ptr(berr),
sshbuf_len(berr));
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
sshbuf_reset(bin);
sshbuf_reset(bout);
sshbuf_reset(berr);
/* Send the suspend signal to the program itself. */
kill(getpid(), SIGTSTP);
/* Reset window sizes in case they have changed */
received_window_change_signal = 1;
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
}
static void
-client_process_net_input(fd_set *readset)
+client_process_net_input(struct ssh *ssh, fd_set *readset)
{
char buf[SSH_IOBUFSZ];
int r, len;
/*
* Read input from the server, and add any such data to the buffer of
* the packet subsystem.
*/
if (FD_ISSET(connection_in, readset)) {
/* Read as much as possible. */
len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
/*
* Received EOF. The remote host has closed the
* connection.
*/
if ((r = sshbuf_putf(stderr_buffer,
"Connection to %.300s closed by remote host.\r\n",
host)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
quit_pending = 1;
return;
}
/*
* There is a kernel bug on Solaris that causes select to
* sometimes wake up even though there is no data available.
*/
if (len < 0 &&
(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
len = 0;
if (len < 0) {
/*
* An error has encountered. Perhaps there is a
* network problem.
*/
if ((r = sshbuf_putf(stderr_buffer,
"Read from remote host %.300s: %.100s\r\n",
host, strerror(errno))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
quit_pending = 1;
return;
}
- packet_process_incoming(buf, len);
+ ssh_packet_process_incoming(ssh, buf, len);
}
}
static void
client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
{
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
char errmsg[256];
int r, tochan;
/*
* If a TTY was explicitly requested, then a failure to allocate
* one is fatal.
*/
if (cr->action == CONFIRM_TTY &&
(options.request_tty == REQUEST_TTY_FORCE ||
options.request_tty == REQUEST_TTY_YES))
cr->action = CONFIRM_CLOSE;
/* XXX suppress on mux _client_ quietmode */
tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
if (type == SSH2_MSG_CHANNEL_SUCCESS) {
debug2("%s request accepted on channel %d",
cr->request_type, c->self);
} else if (type == SSH2_MSG_CHANNEL_FAILURE) {
if (tochan) {
snprintf(errmsg, sizeof(errmsg),
"%s request failed\r\n", cr->request_type);
} else {
snprintf(errmsg, sizeof(errmsg),
"%s request failed on channel %d",
cr->request_type, c->self);
}
/* If error occurred on primary session channel, then exit */
if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
fatal("%s", errmsg);
/*
* If error occurred on mux client, append to
* their stderr.
*/
if (tochan) {
if ((r = sshbuf_put(c->extended, errmsg,
strlen(errmsg))) != 0)
fatal("%s: buffer error %s", __func__,
ssh_err(r));
} else
error("%s", errmsg);
if (cr->action == CONFIRM_TTY) {
/*
* If a TTY allocation error occurred, then arrange
* for the correct TTY to leave raw mode.
*/
if (c->self == session_ident)
leave_raw_mode(0);
else
mux_tty_alloc_failed(ssh, c);
} else if (cr->action == CONFIRM_CLOSE) {
chan_read_failed(ssh, c);
chan_write_failed(ssh, c);
}
}
free(cr);
}
static void
client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx)
{
free(ctx);
}
void
client_expect_confirm(struct ssh *ssh, int id, const char *request,
enum confirm_action action)
{
struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr));
cr->request_type = request;
cr->action = action;
channel_register_status_confirm(ssh, id, client_status_confirm,
client_abandon_status_confirm, cr);
}
void
client_register_global_confirm(global_confirm_cb *cb, void *ctx)
{
struct global_confirm *gc, *last_gc;
/* Coalesce identical callbacks */
last_gc = TAILQ_LAST(&global_confirms, global_confirms);
if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
if (++last_gc->ref_count >= INT_MAX)
fatal("%s: last_gc->ref_count = %d",
__func__, last_gc->ref_count);
return;
}
gc = xcalloc(1, sizeof(*gc));
gc->cb = cb;
gc->ctx = ctx;
gc->ref_count = 1;
TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
}
static void
process_cmdline(struct ssh *ssh)
{
void (*handler)(int);
char *s, *cmd;
int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
struct Forward fwd;
memset(&fwd, 0, sizeof(fwd));
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
handler = signal(SIGINT, SIG_IGN);
cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
if (s == NULL)
goto out;
while (isspace((u_char)*s))
s++;
if (*s == '-')
s++; /* Skip cmdline '-', if any */
if (*s == '\0')
goto out;
if (*s == 'h' || *s == 'H' || *s == '?') {
logit("Commands:");
logit(" -L[bind_address:]port:host:hostport "
"Request local forward");
logit(" -R[bind_address:]port:host:hostport "
"Request remote forward");
logit(" -D[bind_address:]port "
"Request dynamic forward");
logit(" -KL[bind_address:]port "
"Cancel local forward");
logit(" -KR[bind_address:]port "
"Cancel remote forward");
logit(" -KD[bind_address:]port "
"Cancel dynamic forward");
if (!options.permit_local_command)
goto out;
logit(" !args "
"Execute local command");
goto out;
}
if (*s == '!' && options.permit_local_command) {
s++;
ssh_local_cmd(s);
goto out;
}
if (*s == 'K') {
delete = 1;
s++;
}
if (*s == 'L')
local = 1;
else if (*s == 'R')
remote = 1;
else if (*s == 'D')
dynamic = 1;
else {
logit("Invalid command.");
goto out;
}
while (isspace((u_char)*++s))
;
/* XXX update list of forwards in options */
if (delete) {
/* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
if (!parse_forward(&fwd, s, 1, 0)) {
logit("Bad forwarding close specification.");
goto out;
}
if (remote)
ok = channel_request_rforward_cancel(ssh, &fwd) == 0;
else if (dynamic)
ok = channel_cancel_lport_listener(ssh, &fwd,
0, &options.fwd_opts) > 0;
else
ok = channel_cancel_lport_listener(ssh, &fwd,
CHANNEL_CANCEL_PORT_STATIC,
&options.fwd_opts) > 0;
if (!ok) {
logit("Unknown port forwarding.");
goto out;
}
logit("Canceled forwarding.");
} else {
if (!parse_forward(&fwd, s, dynamic, remote)) {
logit("Bad forwarding specification.");
goto out;
}
if (local || dynamic) {
if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) {
logit("Port forwarding failed.");
goto out;
}
} else {
if (channel_request_remote_forwarding(ssh, &fwd) < 0) {
logit("Port forwarding failed.");
goto out;
}
}
logit("Forwarding port.");
}
out:
signal(SIGINT, handler);
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
free(cmd);
free(fwd.listen_host);
free(fwd.listen_path);
free(fwd.connect_host);
free(fwd.connect_path);
}
/* reasons to suppress output of an escape command in help output */
#define SUPPRESS_NEVER 0 /* never suppress, always show */
#define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */
#define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */
#define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */
struct escape_help_text {
const char *cmd;
const char *text;
unsigned int flags;
};
static struct escape_help_text esc_txt[] = {
{".", "terminate session", SUPPRESS_MUXMASTER},
{".", "terminate connection (and any multiplexed sessions)",
SUPPRESS_MUXCLIENT},
{"B", "send a BREAK to the remote system", SUPPRESS_NEVER},
{"C", "open a command line", SUPPRESS_MUXCLIENT},
{"R", "request rekey", SUPPRESS_NEVER},
{"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT},
{"^Z", "suspend ssh", SUPPRESS_MUXCLIENT},
{"#", "list forwarded connections", SUPPRESS_NEVER},
{"&", "background ssh (when waiting for connections to terminate)",
SUPPRESS_MUXCLIENT},
{"?", "this message", SUPPRESS_NEVER},
};
static void
print_escape_help(struct sshbuf *b, int escape_char, int mux_client,
int using_stderr)
{
unsigned int i, suppress_flags;
int r;
if ((r = sshbuf_putf(b,
"%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
suppress_flags =
(mux_client ? SUPPRESS_MUXCLIENT : 0) |
(mux_client ? 0 : SUPPRESS_MUXMASTER) |
(using_stderr ? 0 : SUPPRESS_SYSLOG);
for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) {
if (esc_txt[i].flags & suppress_flags)
continue;
if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n",
escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if ((r = sshbuf_putf(b,
" %c%c - send the escape character by typing it twice\r\n"
"(Note that escapes are only recognized immediately after "
"newline.)\r\n", escape_char, escape_char)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/*
* Process the characters one by one.
*/
static int
process_escapes(struct ssh *ssh, Channel *c,
struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr,
char *buf, int len)
{
pid_t pid;
int r, bytes = 0;
u_int i;
u_char ch;
char *s;
struct escape_filter_ctx *efc = c->filter_ctx == NULL ?
NULL : (struct escape_filter_ctx *)c->filter_ctx;
if (c->filter_ctx == NULL)
return 0;
if (len <= 0)
return (0);
for (i = 0; i < (u_int)len; i++) {
/* Get one character at a time. */
ch = buf[i];
if (efc->escape_pending) {
/* We have previously seen an escape character. */
/* Clear the flag now. */
efc->escape_pending = 0;
/* Process the escaped character. */
switch (ch) {
case '.':
/* Terminate the connection. */
if ((r = sshbuf_putf(berr, "%c.\r\n",
efc->escape_char)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if (c && c->ctl_chan != -1) {
chan_read_failed(ssh, c);
chan_write_failed(ssh, c);
if (c->detach_user) {
c->detach_user(ssh,
c->self, NULL);
}
c->type = SSH_CHANNEL_ABANDONED;
sshbuf_reset(c->input);
chan_ibuf_empty(ssh, c);
return 0;
} else
quit_pending = 1;
return -1;
case 'Z' - 64:
/* XXX support this for mux clients */
if (c && c->ctl_chan != -1) {
char b[16];
noescape:
if (ch == 'Z' - 64)
snprintf(b, sizeof b, "^Z");
else
snprintf(b, sizeof b, "%c", ch);
if ((r = sshbuf_putf(berr,
"%c%s escape not available to "
"multiplexed sessions\r\n",
efc->escape_char, b)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
continue;
}
/* Suspend the program. Inform the user */
if ((r = sshbuf_putf(berr,
"%c^Z [suspend ssh]\r\n",
efc->escape_char)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
/* Restore terminal modes and suspend. */
client_suspend_self(bin, bout, berr);
/* We have been continued. */
continue;
case 'B':
if ((r = sshbuf_putf(berr,
"%cB\r\n", efc->escape_char)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
channel_request_start(ssh, c->self, "break", 0);
if ((r = sshpkt_put_u32(ssh, 1000)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__,
+ fatal("%s: send packet: %s", __func__,
ssh_err(r));
continue;
case 'R':
if (datafellows & SSH_BUG_NOREKEY)
logit("Server does not "
"support re-keying");
else
need_rekeying = 1;
continue;
case 'V':
/* FALLTHROUGH */
case 'v':
if (c && c->ctl_chan != -1)
goto noescape;
if (!log_is_on_stderr()) {
if ((r = sshbuf_putf(berr,
"%c%c [Logging to syslog]\r\n",
efc->escape_char, ch)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
continue;
}
if (ch == 'V' && options.log_level >
SYSLOG_LEVEL_QUIET)
log_change_level(--options.log_level);
if (ch == 'v' && options.log_level <
SYSLOG_LEVEL_DEBUG3)
log_change_level(++options.log_level);
if ((r = sshbuf_putf(berr,
"%c%c [LogLevel %s]\r\n",
efc->escape_char, ch,
log_level_name(options.log_level))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
continue;
case '&':
if (c && c->ctl_chan != -1)
goto noescape;
/*
* Detach the program (continue to serve
* connections, but put in background and no
* more new connections).
*/
/* Restore tty modes. */
leave_raw_mode(
options.request_tty == REQUEST_TTY_FORCE);
/* Stop listening for new connections. */
channel_stop_listening(ssh);
if ((r = sshbuf_putf(berr,
"%c& [backgrounded]\n", efc->escape_char))
!= 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
/* Fork into background. */
pid = fork();
if (pid < 0) {
error("fork: %.100s", strerror(errno));
continue;
}
if (pid != 0) { /* This is the parent. */
/* The parent just exits. */
exit(0);
}
/* The child continues serving connections. */
/* fake EOF on stdin */
if ((r = sshbuf_put_u8(bin, 4)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
return -1;
case '?':
print_escape_help(berr, efc->escape_char,
(c && c->ctl_chan != -1),
log_is_on_stderr());
continue;
case '#':
if ((r = sshbuf_putf(berr, "%c#\r\n",
efc->escape_char)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
s = channel_open_message(ssh);
if ((r = sshbuf_put(berr, s, strlen(s))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
free(s);
continue;
case 'C':
if (c && c->ctl_chan != -1)
goto noescape;
process_cmdline(ssh);
continue;
default:
if (ch != efc->escape_char) {
if ((r = sshbuf_put_u8(bin,
efc->escape_char)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
bytes++;
}
/* Escaped characters fall through here */
break;
}
} else {
/*
* The previous character was not an escape char.
* Check if this is an escape.
*/
if (last_was_cr && ch == efc->escape_char) {
/*
* It is. Set the flag and continue to
* next character.
*/
efc->escape_pending = 1;
continue;
}
}
/*
* Normal character. Record whether it was a newline,
* and append it to the buffer.
*/
last_was_cr = (ch == '\r' || ch == '\n');
if ((r = sshbuf_put_u8(bin, ch)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
bytes++;
}
return bytes;
}
/*
* Get packets from the connection input buffer, and process them as long as
* there are packets available.
*
* Any unknown packets received during the actual
* session cause the session to terminate. This is
* intended to make debugging easier since no
* confirmations are sent. Any compatible protocol
* extensions must be negotiated during the
* preparatory phase.
*/
static void
-client_process_buffered_input_packets(void)
+client_process_buffered_input_packets(struct ssh *ssh)
{
- ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, &quit_pending);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, &quit_pending);
}
/* scan buf[] for '~' before sending data to the peer */
/* Helper: allocate a new escape_filter_ctx and fill in its escape char */
void *
client_new_escape_filter_ctx(int escape_char)
{
struct escape_filter_ctx *ret;
ret = xcalloc(1, sizeof(*ret));
ret->escape_pending = 0;
ret->escape_char = escape_char;
return (void *)ret;
}
/* Free the escape filter context on channel free */
void
client_filter_cleanup(struct ssh *ssh, int cid, void *ctx)
{
free(ctx);
}
int
client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len)
{
if (c->extended_usage != CHAN_EXTENDED_WRITE)
return 0;
return process_escapes(ssh, c, c->input, c->output, c->extended,
buf, len);
}
static void
client_channel_closed(struct ssh *ssh, int id, void *arg)
{
channel_cancel_cleanup(ssh, id);
session_closed = 1;
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
}
/*
* Implements the interactive session with the server. This is called after
* the user has been authenticated, and a command has been started on the
* remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
* used as an escape character for terminating or suspending the session.
*/
int
client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
int ssh2_chan_id)
{
fd_set *readset = NULL, *writeset = NULL;
double start_time, total_time;
int r, max_fd = 0, max_fd2 = 0, len;
u_int64_t ibytes, obytes;
u_int nalloc = 0;
char buf[100];
debug("Entering interactive session.");
if (options.control_master &&
!option_clear_or_none(options.control_path)) {
debug("pledge: id");
if (pledge("stdio rpath wpath cpath unix inet dns recvfd proc exec id tty",
NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
} else if (options.forward_x11 || options.permit_local_command) {
debug("pledge: exec");
if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
} else if (options.update_hostkeys) {
debug("pledge: filesystem full");
if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
} else if (!option_clear_or_none(options.proxy_command) ||
fork_after_authentication_flag) {
debug("pledge: proc");
if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
} else {
debug("pledge: network");
if (pledge("stdio unix inet dns proc tty", NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
}
start_time = monotime_double();
/* Initialize variables. */
last_was_cr = 1;
exit_status = -1;
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
+ connection_in = ssh_packet_get_connection_in(ssh);
+ connection_out = ssh_packet_get_connection_out(ssh);
max_fd = MAXIMUM(connection_in, connection_out);
quit_pending = 0;
/* Initialize buffer. */
if ((stderr_buffer = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- client_init_dispatch();
+ client_init_dispatch(ssh);
/*
* Set signal handlers, (e.g. to restore non-blocking mode)
* but don't overwrite SIG_IGN, matches behaviour from rsh(1)
*/
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, signal_handler);
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, signal_handler);
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
signal(SIGQUIT, signal_handler);
if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
signal(SIGTERM, signal_handler);
signal(SIGWINCH, window_change_handler);
if (have_pty)
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
session_ident = ssh2_chan_id;
if (session_ident != -1) {
if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
channel_register_filter(ssh, session_ident,
client_simple_escape_filter, NULL,
client_filter_cleanup,
client_new_escape_filter_ctx(
escape_char_arg));
}
channel_register_cleanup(ssh, session_ident,
client_channel_closed, 0);
}
/* Main loop of the client for the interactive session mode. */
while (!quit_pending) {
/* Process buffered packets sent by the server. */
- client_process_buffered_input_packets();
+ client_process_buffered_input_packets(ssh);
if (session_closed && !channel_still_open(ssh))
break;
if (ssh_packet_is_rekeying(ssh)) {
debug("rekeying in progress");
} else if (need_rekeying) {
/* manual rekey request */
debug("need rekeying");
if ((r = kex_start_rekex(ssh)) != 0)
fatal("%s: kex_start_rekex: %s", __func__,
ssh_err(r));
need_rekeying = 0;
} else {
/*
* Make packets from buffered channel data, and
* enqueue them for sending to the server.
*/
- if (packet_not_very_much_data_to_write())
+ if (ssh_packet_not_very_much_data_to_write(ssh))
channel_output_poll(ssh);
/*
* Check if the window size has changed, and buffer a
* message about it to the server if so.
*/
client_check_window_change(ssh);
if (quit_pending)
break;
}
/*
* Wait until we have something to do (something becomes
* available on one of the descriptors).
*/
max_fd2 = max_fd;
client_wait_until_can_do_something(ssh, &readset, &writeset,
&max_fd2, &nalloc, ssh_packet_is_rekeying(ssh));
if (quit_pending)
break;
/* Do channel operations unless rekeying in progress. */
if (!ssh_packet_is_rekeying(ssh))
channel_after_select(ssh, readset, writeset);
/* Buffer input from the connection. */
- client_process_net_input(readset);
+ client_process_net_input(ssh, readset);
if (quit_pending)
break;
/*
* Send as much buffered packet data as possible to the
* sender.
*/
if (FD_ISSET(connection_out, writeset))
- packet_write_poll();
+ ssh_packet_write_poll(ssh);
/*
* If we are a backgrounded control master, and the
* timeout has expired without any active client
* connections, then quit.
*/
if (control_persist_exit_time > 0) {
if (monotime() >= control_persist_exit_time) {
debug("ControlPersist timeout expired");
break;
}
}
}
free(readset);
free(writeset);
/* Terminate the session. */
/* Stop watching for window change. */
signal(SIGWINCH, SIG_DFL);
- packet_start(SSH2_MSG_DISCONNECT);
- packet_put_int(SSH2_DISCONNECT_BY_APPLICATION);
- packet_put_cstring("disconnected by user");
- packet_put_cstring(""); /* language tag */
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
+ (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "disconnected by user")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal("%s: send disconnect: %s", __func__, ssh_err(r));
channel_free_all(ssh);
if (have_pty)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
/* restore blocking io */
if (!isatty(fileno(stdin)))
unset_nonblock(fileno(stdin));
if (!isatty(fileno(stdout)))
unset_nonblock(fileno(stdout));
if (!isatty(fileno(stderr)))
unset_nonblock(fileno(stderr));
/*
* If there was no shell or command requested, there will be no remote
* exit status to be returned. In that case, clear error code if the
* connection was deliberately terminated at this end.
*/
if (no_shell_flag && received_signal == SIGTERM) {
received_signal = 0;
exit_status = 0;
}
if (received_signal) {
verbose("Killed by signal %d.", (int) received_signal);
cleanup_exit(0);
}
/*
* In interactive mode (with pseudo tty) display a message indicating
* that the connection has been closed.
*/
if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
if ((r = sshbuf_putf(stderr_buffer,
"Connection to %.64s closed.\r\n", host)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Output any buffered data for stderr. */
if (sshbuf_len(stderr_buffer) > 0) {
len = atomicio(vwrite, fileno(stderr),
(u_char *)sshbuf_ptr(stderr_buffer),
sshbuf_len(stderr_buffer));
if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer))
error("Write failed flushing stderr buffer.");
else if ((r = sshbuf_consume(stderr_buffer, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Clear and free any buffers. */
explicit_bzero(buf, sizeof(buf));
sshbuf_free(stderr_buffer);
/* Report bytes transferred, and transfer rates. */
total_time = monotime_double() - start_time;
- packet_get_bytes(&ibytes, &obytes);
+ ssh_packet_get_bytes(ssh, &ibytes, &obytes);
verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds",
(unsigned long long)obytes, (unsigned long long)ibytes, total_time);
if (total_time > 0)
verbose("Bytes per second: sent %.1f, received %.1f",
obytes / total_time, ibytes / total_time);
/* Return the exit status of the program. */
debug("Exit status %d", exit_status);
return exit_status;
}
/*********/
static Channel *
client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
int rchan, u_int rwindow, u_int rmaxpack)
{
Channel *c = NULL;
struct sshbuf *b = NULL;
char *listen_address, *originator_address;
- u_short listen_port, originator_port;
+ u_int listen_port, originator_port;
int r;
/* Get rest of the packet */
- listen_address = packet_get_string(NULL);
- listen_port = packet_get_int();
- originator_address = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &listen_address, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &listen_port)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &originator_address, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: parse packet: %s", __func__, ssh_err(r));
debug("%s: listen %s port %d, originator %s port %d", __func__,
listen_address, listen_port, originator_address, originator_port);
- c = channel_connect_by_listen_address(ssh, listen_address, listen_port,
- "forwarded-tcpip", originator_address);
+ if (listen_port > 0xffff)
+ error("%s: invalid listen port", __func__);
+ else if (originator_port > 0xffff)
+ error("%s: invalid originator port", __func__);
+ else {
+ c = channel_connect_by_listen_address(ssh,
+ listen_address, listen_port, "forwarded-tcpip",
+ originator_address);
+ }
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
if ((b = sshbuf_new()) == NULL) {
error("%s: alloc reply", __func__);
goto out;
}
/* reconstruct and send to muxclient */
if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */
(r = sshbuf_put_u8(b, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
(r = sshbuf_put_cstring(b, request_type)) != 0 ||
(r = sshbuf_put_u32(b, rchan)) != 0 ||
(r = sshbuf_put_u32(b, rwindow)) != 0 ||
(r = sshbuf_put_u32(b, rmaxpack)) != 0 ||
(r = sshbuf_put_cstring(b, listen_address)) != 0 ||
(r = sshbuf_put_u32(b, listen_port)) != 0 ||
(r = sshbuf_put_cstring(b, originator_address)) != 0 ||
(r = sshbuf_put_u32(b, originator_port)) != 0 ||
(r = sshbuf_put_stringb(c->output, b)) != 0) {
error("%s: compose for muxclient %s", __func__,
ssh_err(r));
goto out;
}
}
out:
sshbuf_free(b);
free(originator_address);
free(listen_address);
return c;
}
static Channel *
client_request_forwarded_streamlocal(struct ssh *ssh,
const char *request_type, int rchan)
{
Channel *c = NULL;
char *listen_path;
+ int r;
/* Get the remote path. */
- listen_path = packet_get_string(NULL);
- /* XXX: Skip reserved field for now. */
- if (packet_get_string_ptr(NULL) == NULL)
- fatal("%s: packet_get_string_ptr failed", __func__);
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL)) != 0 ||
+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* reserved */
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: parse packet: %s", __func__, ssh_err(r));
- debug("%s: %s", __func__, listen_path);
+ debug("%s: request: %s", __func__, listen_path);
c = channel_connect_by_listen_path(ssh, listen_path,
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
free(listen_path);
return c;
}
static Channel *
client_request_x11(struct ssh *ssh, const char *request_type, int rchan)
{
Channel *c = NULL;
char *originator;
- u_short originator_port;
- int sock;
+ u_int originator_port;
+ int r, sock;
if (!options.forward_x11) {
error("Warning: ssh server tried X11 forwarding.");
error("Warning: this is probably a break-in attempt by a "
"malicious server.");
return NULL;
}
if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
verbose("Rejected X11 connection after ForwardX11Timeout "
"expired");
return NULL;
}
- originator = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ fatal("%s: parse packet: %s", __func__, ssh_err(r));
/* XXX check permission */
- debug("client_request_x11: request from %s %d", originator,
+ /* XXX range check originator port? */
+ debug("client_request_x11: request from %s %u", originator,
originator_port);
free(originator);
sock = x11_connect_display(ssh);
if (sock < 0)
return NULL;
c = channel_new(ssh, "x11",
SSH_CHANNEL_X11_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
c->force_drain = 1;
return c;
}
static Channel *
client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
{
Channel *c = NULL;
int r, sock;
if (!options.forward_agent) {
error("Warning: ssh server tried agent forwarding.");
error("Warning: this is probably a break-in attempt by a "
"malicious server.");
return NULL;
}
if ((r = ssh_get_authentication_socket(&sock)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
return NULL;
}
c = channel_new(ssh, "authentication agent connection",
SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
"authentication agent connection", 1);
c->force_drain = 1;
return c;
}
char *
client_request_tun_fwd(struct ssh *ssh, int tun_mode,
int local_tun, int remote_tun)
{
Channel *c;
- int fd;
+ int r, fd;
char *ifname = NULL;
if (tun_mode == SSH_TUNMODE_NO)
return 0;
debug("Requesting tun unit %d in mode %d", local_tun, tun_mode);
/* Open local tunnel device */
if ((fd = tun_open(local_tun, tun_mode, &ifname)) == -1) {
error("Tunnel device open failed.");
return NULL;
}
debug("Tunnel forwarding using interface %s", ifname);
c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;
#if defined(SSH_TUN_FILTER)
if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
channel_register_filter(ssh, c->self, sys_tun_infilter,
sys_tun_outfilter, NULL, NULL);
#endif
- packet_start(SSH2_MSG_CHANNEL_OPEN);
- packet_put_cstring("tun@openssh.com");
- packet_put_int(c->self);
- packet_put_int(c->local_window_max);
- packet_put_int(c->local_maxpacket);
- packet_put_int(tun_mode);
- packet_put_int(remote_tun);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "tun@openssh.com")) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window_max)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_put_u32(ssh, tun_mode)) != 0 ||
+ (r = sshpkt_put_u32(ssh, remote_tun)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
return ifname;
}
/* XXXX move to generic input handler */
static int
client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
- char *ctype;
- int rchan;
- u_int rmaxpack, rwindow, len;
-
- ctype = packet_get_string(&len);
- rchan = packet_get_int();
- rwindow = packet_get_int();
- rmaxpack = packet_get_int();
+ char *ctype = NULL;
+ int r;
+ u_int rchan;
+ size_t len;
+ u_int rmaxpack, rwindow;
+
+ if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
+ goto out;
debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "forwarded-tcpip") == 0) {
c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow,
rmaxpack);
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
c = client_request_forwarded_streamlocal(ssh, ctype, rchan);
} else if (strcmp(ctype, "x11") == 0) {
c = client_request_x11(ssh, ctype, rchan);
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
c = client_request_agent(ssh, ctype, rchan);
}
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
debug3("proxied to downstream: %s", ctype);
} else if (c != NULL) {
debug("confirm %s", ctype);
c->remote_id = rchan;
c->have_remote_id = 1;
c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack;
if (c->type != SSH_CHANNEL_CONNECTING) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
}
} else {
debug("failure %s", ctype);
- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(rchan);
- packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
- packet_put_cstring("open failed");
- packet_put_cstring("");
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
+ (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "open failed")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send failure", __func__);
}
+ r = 0;
+ out:
free(ctype);
- return 0;
+ return r;
}
static int
client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
- int exitval, id, reply, success = 0;
- char *rtype;
-
- id = packet_get_int();
- c = channel_lookup(ssh, id);
+ char *rtype = NULL;
+ u_char reply;
+ u_int id, exitval;
+ int r, success = 0;
+
+ if ((r = sshpkt_get_u32(ssh, &id)) != 0)
+ return r;
+ if (id <= INT_MAX)
+ c = channel_lookup(ssh, id);
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
- rtype = packet_get_string(NULL);
- reply = packet_get_char();
+ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &reply)) != 0)
+ goto out;
- debug("client_input_channel_req: channel %d rtype %s reply %d",
+ debug("client_input_channel_req: channel %u rtype %s reply %d",
id, rtype, reply);
- if (id == -1) {
- error("client_input_channel_req: request for channel -1");
- } else if (c == NULL) {
+ if (c == NULL) {
error("client_input_channel_req: channel %d: "
"unknown channel", id);
} else if (strcmp(rtype, "eow@openssh.com") == 0) {
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ goto out;
chan_rcvd_eow(ssh, c);
} else if (strcmp(rtype, "exit-status") == 0) {
- exitval = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &exitval)) != 0)
+ goto out;
if (c->ctl_chan != -1) {
mux_exit_message(ssh, c, exitval);
success = 1;
- } else if (id == session_ident) {
+ } else if ((int)id == session_ident) {
/* Record exit value of local session */
success = 1;
exit_status = exitval;
} else {
/* Probably for a mux channel that has already closed */
debug("%s: no sink for exit-status on channel %d",
__func__, id);
}
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ goto out;
}
if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) {
if (!c->have_remote_id)
fatal("%s: channel %d: no remote_id",
__func__, c->self);
- packet_start(success ?
- SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
- packet_put_int(c->remote_id);
- packet_send();
+ if ((r = sshpkt_start(ssh, success ?
+ SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send failure", __func__);
}
+ r = 0;
+ out:
free(rtype);
- return 0;
+ return r;
}
struct hostkeys_update_ctx {
/* The hostname and (optionally) IP address string for the server */
char *host_str, *ip_str;
/*
* Keys received from the server and a flag for each indicating
* whether they already exist in known_hosts.
* keys_seen is filled in by hostkeys_find() and later (for new
* keys) by client_global_hostkeys_private_confirm().
*/
struct sshkey **keys;
int *keys_seen;
size_t nkeys, nnew;
/*
* Keys that are in known_hosts, but were not present in the update
* from the server (i.e. scheduled to be deleted).
* Filled in by hostkeys_find().
*/
struct sshkey **old_keys;
size_t nold;
};
static void
hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
{
size_t i;
if (ctx == NULL)
return;
for (i = 0; i < ctx->nkeys; i++)
sshkey_free(ctx->keys[i]);
free(ctx->keys);
free(ctx->keys_seen);
for (i = 0; i < ctx->nold; i++)
sshkey_free(ctx->old_keys[i]);
free(ctx->old_keys);
free(ctx->host_str);
free(ctx->ip_str);
free(ctx);
}
static int
hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
{
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
size_t i;
struct sshkey **tmp;
if (l->status != HKF_STATUS_MATCHED || l->key == NULL)
return 0;
/* Mark off keys we've already seen for this host */
for (i = 0; i < ctx->nkeys; i++) {
if (sshkey_equal(l->key, ctx->keys[i])) {
debug3("%s: found %s key at %s:%ld", __func__,
sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum);
ctx->keys_seen[i] = 1;
return 0;
}
}
/* This line contained a key that not offered by the server */
debug3("%s: deprecated %s key at %s:%ld", __func__,
sshkey_ssh_name(l->key), l->path, l->linenum);
if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1,
sizeof(*ctx->old_keys))) == NULL)
fatal("%s: recallocarray failed nold = %zu",
__func__, ctx->nold);
ctx->old_keys = tmp;
ctx->old_keys[ctx->nold++] = l->key;
l->key = NULL;
return 0;
}
static void
update_known_hosts(struct hostkeys_update_ctx *ctx)
{
int r, was_raw = 0;
int loglevel = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK ?
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE;
char *fp, *response;
size_t i;
for (i = 0; i < ctx->nkeys; i++) {
if (ctx->keys_seen[i] != 2)
continue;
if ((fp = sshkey_fingerprint(ctx->keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
do_log2(loglevel, "Learned new hostkey: %s %s",
sshkey_type(ctx->keys[i]), fp);
free(fp);
}
for (i = 0; i < ctx->nold; i++) {
if ((fp = sshkey_fingerprint(ctx->old_keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
do_log2(loglevel, "Deprecating obsolete hostkey: %s %s",
sshkey_type(ctx->old_keys[i]), fp);
free(fp);
}
if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
if (get_saved_tio() != NULL) {
leave_raw_mode(1);
was_raw = 1;
}
response = NULL;
for (i = 0; !quit_pending && i < 3; i++) {
free(response);
response = read_passphrase("Accept updated hostkeys? "
"(yes/no): ", RP_ECHO);
if (strcasecmp(response, "yes") == 0)
break;
else if (quit_pending || response == NULL ||
strcasecmp(response, "no") == 0) {
options.update_hostkeys = 0;
break;
} else {
do_log2(loglevel, "Please enter "
"\"yes\" or \"no\"");
}
}
if (quit_pending || i >= 3 || response == NULL)
options.update_hostkeys = 0;
free(response);
if (was_raw)
enter_raw_mode(1);
}
/*
* Now that all the keys are verified, we can go ahead and replace
* them in known_hosts (assuming SSH_UPDATE_HOSTKEYS_ASK didn't
* cancel the operation).
*/
if (options.update_hostkeys != 0 &&
(r = hostfile_replace_entries(options.user_hostfiles[0],
ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys,
options.hash_known_hosts, 0,
options.fingerprint_hash)) != 0)
error("%s: hostfile_replace_entries failed: %s",
__func__, ssh_err(r));
}
static void
client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
u_int32_t seq, void *_ctx)
{
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
size_t i, ndone;
struct sshbuf *signdata;
int r, kexsigtype, use_kexsigtype;
const u_char *sig;
size_t siglen;
if (ctx->nnew == 0)
fatal("%s: ctx->nnew == 0", __func__); /* sanity */
if (type != SSH2_MSG_REQUEST_SUCCESS) {
error("Server failed to confirm ownership of "
"private host keys");
hostkeys_update_ctx_free(ctx);
return;
}
kexsigtype = sshkey_type_plain(
sshkey_type_from_name(ssh->kex->hostkey_alg));
if ((signdata = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Don't want to accidentally accept an unbound signature */
if (ssh->kex->session_id_len == 0)
fatal("%s: ssh->kex->session_id_len == 0", __func__);
/*
* Expect a signature for each of the ctx->nnew private keys we
* haven't seen before. They will be in the same order as the
* ctx->keys where the corresponding ctx->keys_seen[i] == 0.
*/
for (ndone = i = 0; i < ctx->nkeys; i++) {
if (ctx->keys_seen[i])
continue;
/* Prepare data to be signed: session ID, unique string, key */
sshbuf_reset(signdata);
if ( (r = sshbuf_put_cstring(signdata,
"hostkeys-prove-00@openssh.com")) != 0 ||
(r = sshbuf_put_string(signdata, ssh->kex->session_id,
ssh->kex->session_id_len)) != 0 ||
(r = sshkey_puts(ctx->keys[i], signdata)) != 0)
fatal("%s: failed to prepare signature: %s",
__func__, ssh_err(r));
/* Extract and verify signature */
if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) {
error("%s: couldn't parse message: %s",
__func__, ssh_err(r));
goto out;
}
/*
* For RSA keys, prefer to use the signature type negotiated
* during KEX to the default (SHA1).
*/
use_kexsigtype = kexsigtype == KEY_RSA &&
sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
sshbuf_ptr(signdata), sshbuf_len(signdata),
use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0) {
error("%s: server gave bad signature for %s key %zu",
__func__, sshkey_type(ctx->keys[i]), i);
goto out;
}
/* Key is good. Mark it as 'seen' */
ctx->keys_seen[i] = 2;
ndone++;
}
if (ndone != ctx->nnew)
fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__,
ndone, ctx->nnew); /* Shouldn't happen */
- ssh_packet_check_eom(ssh);
+ if ((r = sshpkt_get_end(ssh)) != 0) {
+ error("%s: protocol error", __func__);
+ goto out;
+ }
/* Make the edits to known_hosts */
update_known_hosts(ctx);
out:
hostkeys_update_ctx_free(ctx);
}
/*
* Returns non-zero if the key is accepted by HostkeyAlgorithms.
* Made slightly less trivial by the multiple RSA signature algorithm names.
*/
static int
key_accepted_by_hostkeyalgs(const struct sshkey *key)
{
const char *ktype = sshkey_ssh_name(key);
const char *hostkeyalgs = options.hostkeyalgorithms != NULL ?
options.hostkeyalgorithms : KEX_DEFAULT_PK_ALG;
if (key == NULL || key->type == KEY_UNSPEC)
return 0;
if (key->type == KEY_RSA &&
(match_pattern_list("rsa-sha2-256", hostkeyalgs, 0) == 1 ||
match_pattern_list("rsa-sha2-512", hostkeyalgs, 0) == 1))
return 1;
return match_pattern_list(ktype, hostkeyalgs, 0) == 1;
}
/*
* Handle hostkeys-00@openssh.com global request to inform the client of all
* the server's hostkeys. The keys are checked against the user's
* HostkeyAlgorithms preference before they are accepted.
*/
static int
-client_input_hostkeys(void)
+client_input_hostkeys(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
const u_char *blob = NULL;
size_t i, len = 0;
struct sshbuf *buf = NULL;
struct sshkey *key = NULL, **tmp;
int r;
char *fp;
static int hostkeys_seen = 0; /* XXX use struct ssh */
extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */
struct hostkeys_update_ctx *ctx = NULL;
if (hostkeys_seen)
fatal("%s: server already sent hostkeys", __func__);
if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK &&
options.batch_mode)
return 1; /* won't ask in batchmode, so don't even try */
if (!options.update_hostkeys || options.num_user_hostfiles <= 0)
return 1;
ctx = xcalloc(1, sizeof(*ctx));
while (ssh_packet_remaining(ssh) > 0) {
sshkey_free(key);
key = NULL;
if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) {
error("%s: couldn't parse message: %s",
__func__, ssh_err(r));
goto out;
}
if ((r = sshkey_from_blob(blob, len, &key)) != 0) {
error("%s: parse key: %s", __func__, ssh_err(r));
goto out;
}
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
debug3("%s: received %s key %s", __func__,
sshkey_type(key), fp);
free(fp);
if (!key_accepted_by_hostkeyalgs(key)) {
debug3("%s: %s key not permitted by HostkeyAlgorithms",
__func__, sshkey_ssh_name(key));
continue;
}
/* Skip certs */
if (sshkey_is_cert(key)) {
debug3("%s: %s key is a certificate; skipping",
__func__, sshkey_ssh_name(key));
continue;
}
/* Ensure keys are unique */
for (i = 0; i < ctx->nkeys; i++) {
if (sshkey_equal(key, ctx->keys[i])) {
error("%s: received duplicated %s host key",
__func__, sshkey_ssh_name(key));
goto out;
}
}
/* Key is good, record it */
if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1,
sizeof(*ctx->keys))) == NULL)
fatal("%s: recallocarray failed nkeys = %zu",
__func__, ctx->nkeys);
ctx->keys = tmp;
ctx->keys[ctx->nkeys++] = key;
key = NULL;
}
if (ctx->nkeys == 0) {
debug("%s: server sent no hostkeys", __func__);
goto out;
}
if ((ctx->keys_seen = calloc(ctx->nkeys,
sizeof(*ctx->keys_seen))) == NULL)
fatal("%s: calloc failed", __func__);
get_hostfile_hostname_ipaddr(host,
options.check_host_ip ? (struct sockaddr *)&hostaddr : NULL,
options.port, &ctx->host_str,
options.check_host_ip ? &ctx->ip_str : NULL);
/* Find which keys we already know about. */
if ((r = hostkeys_foreach(options.user_hostfiles[0], hostkeys_find,
ctx, ctx->host_str, ctx->ip_str,
HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) {
error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
goto out;
}
/* Figure out if we have any new keys to add */
ctx->nnew = 0;
for (i = 0; i < ctx->nkeys; i++) {
if (!ctx->keys_seen[i])
ctx->nnew++;
}
debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove",
__func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold);
if (ctx->nnew == 0 && ctx->nold != 0) {
/* We have some keys to remove. Just do it. */
update_known_hosts(ctx);
} else if (ctx->nnew != 0) {
/*
* We have received hitherto-unseen keys from the server.
* Ask the server to confirm ownership of the private halves.
*/
debug3("%s: asking server to prove ownership for %zu keys",
__func__, ctx->nnew);
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh,
"hostkeys-prove-00@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 1)) != 0) /* bool: want reply */
fatal("%s: cannot prepare packet: %s",
__func__, ssh_err(r));
if ((buf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
for (i = 0; i < ctx->nkeys; i++) {
if (ctx->keys_seen[i])
continue;
sshbuf_reset(buf);
if ((r = sshkey_putb(ctx->keys[i], buf)) != 0)
fatal("%s: sshkey_putb: %s",
__func__, ssh_err(r));
if ((r = sshpkt_put_stringb(ssh, buf)) != 0)
fatal("%s: sshpkt_put_string: %s",
__func__, ssh_err(r));
}
if ((r = sshpkt_send(ssh)) != 0)
fatal("%s: sshpkt_send: %s", __func__, ssh_err(r));
client_register_global_confirm(
client_global_hostkeys_private_confirm, ctx);
ctx = NULL; /* will be freed in callback */
}
/* Success */
out:
hostkeys_update_ctx_free(ctx);
sshkey_free(key);
sshbuf_free(buf);
/*
* NB. Return success for all cases. The server doesn't need to know
* what the client does with its hosts file.
*/
return 1;
}
static int
client_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
{
char *rtype;
- int want_reply;
- int success = 0;
+ u_char want_reply;
+ int r, success = 0;
- rtype = packet_get_cstring(NULL);
- want_reply = packet_get_char();
+ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
+ goto out;
debug("client_input_global_request: rtype %s want_reply %d",
rtype, want_reply);
if (strcmp(rtype, "hostkeys-00@openssh.com") == 0)
- success = client_input_hostkeys();
+ success = client_input_hostkeys(ssh);
if (want_reply) {
- packet_start(success ?
- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS :
+ SSH2_MSG_REQUEST_FAILURE)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ goto out;
}
+ r = 0;
+ out:
free(rtype);
- return 0;
+ return r;
}
void
client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd,
char **env)
{
- int i, j, matched, len;
+ int i, j, matched, len, r;
char *name, *val;
Channel *c = NULL;
debug2("%s: id %d", __func__, id);
if ((c = channel_lookup(ssh, id)) == NULL)
fatal("%s: channel %d: unknown channel", __func__, id);
- packet_set_interactive(want_tty,
+ ssh_packet_set_interactive(ssh, want_tty,
options.ip_qos_interactive, options.ip_qos_bulk);
if (want_tty) {
struct winsize ws;
/* Store window size in the packet. */
if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
memset(&ws, 0, sizeof(ws));
channel_request_start(ssh, id, "pty-req", 1);
client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY);
- packet_put_cstring(term != NULL ? term : "");
- packet_put_int((u_int)ws.ws_col);
- packet_put_int((u_int)ws.ws_row);
- packet_put_int((u_int)ws.ws_xpixel);
- packet_put_int((u_int)ws.ws_ypixel);
+ if ((r = sshpkt_put_cstring(ssh, term != NULL ? term : ""))
+ != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0)
+ fatal("%s: build packet: %s", __func__, ssh_err(r));
if (tiop == NULL)
tiop = get_saved_tio();
ssh_tty_make_modes(ssh, -1, tiop);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send packet: %s", __func__, ssh_err(r));
/* XXX wait for reply */
c->client_tty = 1;
}
/* Transfer any environment variables from client to server */
if (options.num_send_env != 0 && env != NULL) {
debug("Sending environment.");
for (i = 0; env[i] != NULL; i++) {
/* Split */
name = xstrdup(env[i]);
if ((val = strchr(name, '=')) == NULL) {
free(name);
continue;
}
*val++ = '\0';
matched = 0;
for (j = 0; j < options.num_send_env; j++) {
if (match_pattern(name, options.send_env[j])) {
matched = 1;
break;
}
}
if (!matched) {
debug3("Ignored env %s", name);
free(name);
continue;
}
debug("Sending env %s = %s", name, val);
channel_request_start(ssh, id, "env", 0);
- packet_put_cstring(name);
- packet_put_cstring(val);
- packet_send();
+ if ((r = sshpkt_put_cstring(ssh, name)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, val)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: send packet: %s",
+ __func__, ssh_err(r));
+ }
free(name);
}
}
for (i = 0; i < options.num_setenv; i++) {
/* Split */
name = xstrdup(options.setenv[i]);
if ((val = strchr(name, '=')) == NULL) {
free(name);
continue;
}
*val++ = '\0';
debug("Setting env %s = %s", name, val);
channel_request_start(ssh, id, "env", 0);
- packet_put_cstring(name);
- packet_put_cstring(val);
- packet_send();
+ if ((r = sshpkt_put_cstring(ssh, name)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, val)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send packet: %s", __func__, ssh_err(r));
free(name);
}
len = sshbuf_len(cmd);
if (len > 0) {
if (len > 900)
len = 900;
if (want_subsystem) {
debug("Sending subsystem: %.*s",
len, (const u_char*)sshbuf_ptr(cmd));
channel_request_start(ssh, id, "subsystem", 1);
client_expect_confirm(ssh, id, "subsystem",
CONFIRM_CLOSE);
} else {
debug("Sending command: %.*s",
len, (const u_char*)sshbuf_ptr(cmd));
channel_request_start(ssh, id, "exec", 1);
client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE);
}
- packet_put_string(sshbuf_ptr(cmd), sshbuf_len(cmd));
- packet_send();
+ if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: send command: %s", __func__, ssh_err(r));
} else {
channel_request_start(ssh, id, "shell", 1);
client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0) {
+ fatal("%s: send shell request: %s",
+ __func__, ssh_err(r));
+ }
}
}
static void
-client_init_dispatch(void)
+client_init_dispatch(struct ssh *ssh)
{
- dispatch_init(&dispatch_protocol_error);
-
- dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
- dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
- dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
- dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
- dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
- dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
- dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
- dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
+ ssh_dispatch_init(ssh, &dispatch_protocol_error);
+
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm);
+ ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request);
/* rekeying */
- dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
/* global request reply messages */
- dispatch_set(SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
- dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply);
}
void
client_stop_mux(void)
{
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
/*
* If we are in persist mode, or don't have a shell, signal that we
* should close when all active channels are closed.
*/
if (options.control_persist || no_shell_flag) {
session_closed = 1;
setproctitle("[stopped mux]");
}
}
/* client specific fatal cleanup */
void
cleanup_exit(int i)
{
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
leave_non_blocking();
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
ssh_kill_proxy_command();
_exit(i);
}
diff --git a/config.h.in b/config.h.in
index 91b65db8f349..05b7206df17f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1,1951 +1,1975 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address
*/
#undef AIX_GETNAMEINFO_HACK
/* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */
#undef AIX_LOGINFAILED_4ARG
/* System only supports IPv4 audit records */
#undef AU_IPv4
/* Define if your resolver libs need this for getrrsetbyname */
#undef BIND_8_COMPAT
/* The system has incomplete BSM API */
#undef BROKEN_BSM_API
/* Define if cmsg_type is not passed correctly */
#undef BROKEN_CMSG_TYPE
/* getaddrinfo is broken (if present) */
#undef BROKEN_GETADDRINFO
/* getgroups(0,NULL) will return -1 */
#undef BROKEN_GETGROUPS
/* FreeBSD glob does not do what we need */
#undef BROKEN_GLOB
/* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */
#undef BROKEN_INET_NTOA
/* Define if your struct dirent expects you to allocate extra space for d_name
*/
#undef BROKEN_ONE_BYTE_DIRENT_D_NAME
/* Can't do comparisons on readv */
#undef BROKEN_READV_COMPARISON
/* NetBSD read function is sometimes redirected, breaking atomicio comparisons
against it */
#undef BROKEN_READ_COMPARISON
/* realpath does not work with nonexistent files */
#undef BROKEN_REALPATH
/* Needed for NeXT */
#undef BROKEN_SAVED_UIDS
/* Define if your setregid() is broken */
#undef BROKEN_SETREGID
/* Define if your setresgid() is broken */
#undef BROKEN_SETRESGID
/* Define if your setresuid() is broken */
#undef BROKEN_SETRESUID
/* Define if your setreuid() is broken */
#undef BROKEN_SETREUID
/* LynxOS has broken setvbuf() implementation */
#undef BROKEN_SETVBUF
/* QNX shadow support is broken */
#undef BROKEN_SHADOW_EXPIRE
/* Define if your snprintf is busted */
#undef BROKEN_SNPRINTF
/* strndup broken, see APAR IY61211 */
#undef BROKEN_STRNDUP
/* strnlen broken, see APAR IY62551 */
#undef BROKEN_STRNLEN
/* strnvis detected broken */
#undef BROKEN_STRNVIS
/* tcgetattr with ICANON may hang */
#undef BROKEN_TCGETATTR_ICANON
/* updwtmpx is broken (if present) */
#undef BROKEN_UPDWTMPX
/* Define if you have BSD auth support */
#undef BSD_AUTH
/* Define if you want to specify the path to your lastlog file */
#undef CONF_LASTLOG_FILE
/* Define if you want to specify the path to your utmp file */
#undef CONF_UTMP_FILE
/* Define if you want to specify the path to your wtmpx file */
#undef CONF_WTMPX_FILE
/* Define if you want to specify the path to your wtmp file */
#undef CONF_WTMP_FILE
/* Define if your platform needs to skip post auth file descriptor passing */
#undef DISABLE_FD_PASSING
/* Define if you don't want to use lastlog */
#undef DISABLE_LASTLOG
/* Define if you don't want to use your system's login() call */
#undef DISABLE_LOGIN
/* Define if you don't want to use pututline() etc. to write [uw]tmp */
#undef DISABLE_PUTUTLINE
/* Define if you don't want to use pututxline() etc. to write [uw]tmpx */
#undef DISABLE_PUTUTXLINE
/* Define if you want to disable shadow passwords */
#undef DISABLE_SHADOW
/* Define if you don't want to use utmp */
#undef DISABLE_UTMP
/* Define if you don't want to use utmpx */
#undef DISABLE_UTMPX
/* Define if you don't want to use wtmp */
#undef DISABLE_WTMP
/* Define if you don't want to use wtmpx */
#undef DISABLE_WTMPX
/* Enable for PKCS#11 support */
#undef ENABLE_PKCS11
/* define if fflush(NULL) does not work */
#undef FFLUSH_NULL_BUG
/* File names may not contain backslash characters */
#undef FILESYSTEM_NO_BACKSLASH
/* fsid_t has member val */
#undef FSID_HAS_VAL
/* fsid_t has member __val */
#undef FSID_HAS___VAL
/* getpgrp takes one arg */
#undef GETPGRP_VOID
/* Conflicting defs for getspnam */
#undef GETSPNAM_CONFLICTING_DEFS
/* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */
#undef GLOB_HAS_ALTDIRFUNC
/* Define if your system glob() function has gl_matchc options in glob_t */
#undef GLOB_HAS_GL_MATCHC
/* Define if your system glob() function has gl_statv options in glob_t */
#undef GLOB_HAS_GL_STATV
/* Define this if you want GSSAPI support in the version 2 protocol */
#undef GSSAPI
/* Define if you want to use shadow password expire field */
#undef HAS_SHADOW_EXPIRE
/* Define if your system uses access rights style file descriptor passing */
#undef HAVE_ACCRIGHTS_IN_MSGHDR
/* Define if you have ut_addr in utmp.h */
#undef HAVE_ADDR_IN_UTMP
/* Define if you have ut_addr in utmpx.h */
#undef HAVE_ADDR_IN_UTMPX
/* Define if you have ut_addr_v6 in utmp.h */
#undef HAVE_ADDR_V6_IN_UTMP
/* Define if you have ut_addr_v6 in utmpx.h */
#undef HAVE_ADDR_V6_IN_UTMPX
/* Define to 1 if you have the `arc4random' function. */
#undef HAVE_ARC4RANDOM
/* Define to 1 if you have the `arc4random_buf' function. */
#undef HAVE_ARC4RANDOM_BUF
/* Define to 1 if you have the `arc4random_stir' function. */
#undef HAVE_ARC4RANDOM_STIR
/* Define to 1 if you have the `arc4random_uniform' function. */
#undef HAVE_ARC4RANDOM_UNIFORM
/* Define to 1 if you have the `asprintf' function. */
#undef HAVE_ASPRINTF
/* OpenBSD's gcc has bounded */
#undef HAVE_ATTRIBUTE__BOUNDED__
/* Have attribute nonnull */
#undef HAVE_ATTRIBUTE__NONNULL__
/* OpenBSD's gcc has sentinel */
#undef HAVE_ATTRIBUTE__SENTINEL__
/* Define to 1 if you have the `aug_get_machine' function. */
#undef HAVE_AUG_GET_MACHINE
/* Define to 1 if you have the `b64_ntop' function. */
#undef HAVE_B64_NTOP
/* Define to 1 if you have the `b64_pton' function. */
#undef HAVE_B64_PTON
/* Define if you have the basename function. */
#undef HAVE_BASENAME
/* Define to 1 if you have the `bcopy' function. */
#undef HAVE_BCOPY
/* Define to 1 if you have the `bcrypt_pbkdf' function. */
#undef HAVE_BCRYPT_PBKDF
/* Define to 1 if you have the `bindresvport_sa' function. */
#undef HAVE_BINDRESVPORT_SA
/* Define to 1 if you have the `blf_enc' function. */
#undef HAVE_BLF_ENC
/* Define to 1 if you have the <blf.h> header file. */
#undef HAVE_BLF_H
/* Define to 1 if you have the `Blowfish_expand0state' function. */
#undef HAVE_BLOWFISH_EXPAND0STATE
/* Define to 1 if you have the `Blowfish_expandstate' function. */
#undef HAVE_BLOWFISH_EXPANDSTATE
/* Define to 1 if you have the `Blowfish_initstate' function. */
#undef HAVE_BLOWFISH_INITSTATE
/* Define to 1 if you have the `Blowfish_stream2word' function. */
#undef HAVE_BLOWFISH_STREAM2WORD
/* Define to 1 if you have the `BN_is_prime_ex' function. */
#undef HAVE_BN_IS_PRIME_EX
/* Define to 1 if you have the <bsd/libutil.h> header file. */
#undef HAVE_BSD_LIBUTIL_H
/* Define to 1 if you have the <bsm/audit.h> header file. */
#undef HAVE_BSM_AUDIT_H
/* Define to 1 if you have the <bstring.h> header file. */
#undef HAVE_BSTRING_H
/* Define to 1 if you have the `bzero' function. */
#undef HAVE_BZERO
/* calloc(0, x) returns NULL */
#undef HAVE_CALLOC
/* Define to 1 if you have the `cap_rights_limit' function. */
#undef HAVE_CAP_RIGHTS_LIMIT
/* Define to 1 if you have the `clock' function. */
#undef HAVE_CLOCK
/* Have clock_gettime */
#undef HAVE_CLOCK_GETTIME
/* define if you have clock_t data type */
#undef HAVE_CLOCK_T
/* Define to 1 if you have the `closefrom' function. */
#undef HAVE_CLOSEFROM
/* Define if gai_strerror() returns const char * */
#undef HAVE_CONST_GAI_STRERROR_PROTO
/* Define if your system uses ancillary data style file descriptor passing */
#undef HAVE_CONTROL_IN_MSGHDR
/* Define to 1 if you have the `crypt' function. */
#undef HAVE_CRYPT
/* Define to 1 if you have the <crypto/sha2.h> header file. */
#undef HAVE_CRYPTO_SHA2_H
/* Define to 1 if you have the <crypt.h> header file. */
#undef HAVE_CRYPT_H
/* Define if you are on Cygwin */
#undef HAVE_CYGWIN
/* Define if your libraries define daemon() */
#undef HAVE_DAEMON
/* Define to 1 if you have the declaration of `AI_NUMERICSERV', and to 0 if
you don't. */
#undef HAVE_DECL_AI_NUMERICSERV
/* Define to 1 if you have the declaration of `authenticate', and to 0 if you
don't. */
#undef HAVE_DECL_AUTHENTICATE
/* Define to 1 if you have the declaration of `bzero', and to 0 if you don't.
*/
#undef HAVE_DECL_BZERO
/* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you
don't. */
#undef HAVE_DECL_GLOB_NOMATCH
/* Define to 1 if you have the declaration of `GSS_C_NT_HOSTBASED_SERVICE',
and to 0 if you don't. */
#undef HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE
/* Define to 1 if you have the declaration of `howmany', and to 0 if you
don't. */
#undef HAVE_DECL_HOWMANY
/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
don't. */
#undef HAVE_DECL_H_ERRNO
/* Define to 1 if you have the declaration of `loginfailed', and to 0 if you
don't. */
#undef HAVE_DECL_LOGINFAILED
/* Define to 1 if you have the declaration of `loginrestrictions', and to 0 if
you don't. */
#undef HAVE_DECL_LOGINRESTRICTIONS
/* Define to 1 if you have the declaration of `loginsuccess', and to 0 if you
don't. */
#undef HAVE_DECL_LOGINSUCCESS
/* Define to 1 if you have the declaration of `MAXSYMLINKS', and to 0 if you
don't. */
#undef HAVE_DECL_MAXSYMLINKS
/* Define to 1 if you have the declaration of `NFDBITS', and to 0 if you
don't. */
#undef HAVE_DECL_NFDBITS
/* Define to 1 if you have the declaration of `offsetof', and to 0 if you
don't. */
#undef HAVE_DECL_OFFSETOF
/* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you
don't. */
#undef HAVE_DECL_O_NONBLOCK
/* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you
don't. */
#undef HAVE_DECL_PASSWDEXPIRED
/* Define to 1 if you have the declaration of `readv', and to 0 if you don't.
*/
#undef HAVE_DECL_READV
/* Define to 1 if you have the declaration of `setauthdb', and to 0 if you
don't. */
#undef HAVE_DECL_SETAUTHDB
/* Define to 1 if you have the declaration of `SHUT_RD', and to 0 if you
don't. */
#undef HAVE_DECL_SHUT_RD
/* Define to 1 if you have the declaration of `writev', and to 0 if you don't.
*/
#undef HAVE_DECL_WRITEV
/* Define to 1 if you have the declaration of `_getlong', and to 0 if you
don't. */
#undef HAVE_DECL__GETLONG
/* Define to 1 if you have the declaration of `_getshort', and to 0 if you
don't. */
#undef HAVE_DECL__GETSHORT
/* Define to 1 if you have the `DES_crypt' function. */
#undef HAVE_DES_CRYPT
/* Define if you have /dev/ptmx */
#undef HAVE_DEV_PTMX
/* Define if you have /dev/ptc */
#undef HAVE_DEV_PTS_AND_PTC
-/* Define if libcrypto has DH_get0_key */
+/* Define to 1 if you have the `DH_get0_key' function. */
#undef HAVE_DH_GET0_KEY
-/* Define if libcrypto has DH_get0_pqg */
+/* Define to 1 if you have the `DH_get0_pqg' function. */
#undef HAVE_DH_GET0_PQG
-/* Define if libcrypto has DH_set0_key */
+/* Define to 1 if you have the `DH_set0_key' function. */
#undef HAVE_DH_SET0_KEY
-/* Define if libcrypto has DH_set0_pqg */
+/* Define to 1 if you have the `DH_set0_pqg' function. */
#undef HAVE_DH_SET0_PQG
-/* Define if libcrypto has DH_set_length */
+/* Define to 1 if you have the `DH_set_length' function. */
#undef HAVE_DH_SET_LENGTH
/* Define to 1 if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
/* Define to 1 if you have the `dirfd' function. */
#undef HAVE_DIRFD
/* Define to 1 if you have the `dirname' function. */
#undef HAVE_DIRNAME
/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */
#undef HAVE_DSA_GENERATE_PARAMETERS_EX
-/* Define if libcrypto has DSA_get0_key */
+/* Define to 1 if you have the `DSA_get0_key' function. */
#undef HAVE_DSA_GET0_KEY
-/* Define if libcrypto has DSA_get0_pqg */
+/* Define to 1 if you have the `DSA_get0_pqg' function. */
#undef HAVE_DSA_GET0_PQG
-/* Define if libcrypto has DSA_set0_key */
+/* Define to 1 if you have the `DSA_set0_key' function. */
#undef HAVE_DSA_SET0_KEY
-/* Define if libcrypto has DSA_set0_pqg */
+/* Define to 1 if you have the `DSA_set0_pqg' function. */
#undef HAVE_DSA_SET0_PQG
-/* Define if libcrypto has DSA_SIG_get0 */
+/* Define to 1 if you have the `DSA_SIG_get0' function. */
#undef HAVE_DSA_SIG_GET0
-/* Define if libcrypto has DSA_SIG_set0 */
+/* Define to 1 if you have the `DSA_SIG_set0' function. */
#undef HAVE_DSA_SIG_SET0
-/* Define if libcrypto has ECDSA_SIG_get0 */
+/* Define to 1 if you have the `ECDSA_SIG_get0' function. */
#undef HAVE_ECDSA_SIG_GET0
-/* Define if libcrypto has ECDSA_SIG_set0 */
+/* Define to 1 if you have the `ECDSA_SIG_set0' function. */
#undef HAVE_ECDSA_SIG_SET0
+/* Define to 1 if you have the `EC_KEY_METHOD_new' function. */
+#undef HAVE_EC_KEY_METHOD_NEW
+
/* Define to 1 if you have the <elf.h> header file. */
#undef HAVE_ELF_H
/* Define to 1 if you have the `endgrent' function. */
#undef HAVE_ENDGRENT
/* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define to 1 if you have the `endutent' function. */
#undef HAVE_ENDUTENT
/* Define to 1 if you have the `endutxent' function. */
#undef HAVE_ENDUTXENT
/* Define to 1 if you have the `err' function. */
#undef HAVE_ERR
/* Define to 1 if you have the `errx' function. */
#undef HAVE_ERRX
/* Define to 1 if you have the <err.h> header file. */
#undef HAVE_ERR_H
/* Define if your system has /etc/default/login */
#undef HAVE_ETC_DEFAULT_LOGIN
-/* Define if libcrypto has EVP_CIPHER_CTX_ctrl */
+/* Define to 1 if you have the `EVP_CIPHER_CTX_ctrl' function. */
#undef HAVE_EVP_CIPHER_CTX_CTRL
-/* Define if libcrypto has EVP_CIPHER_CTX_set_iv */
+/* Define to 1 if you have the `EVP_CIPHER_CTX_get_iv' function. */
#undef HAVE_EVP_CIPHER_CTX_GET_IV
-/* Define if libcrypto has EVP_CIPHER_CTX_iv */
+/* Define to 1 if you have the `EVP_CIPHER_CTX_iv' function. */
#undef HAVE_EVP_CIPHER_CTX_IV
-/* Define if libcrypto has EVP_CIPHER_CTX_iv_noconst */
+/* Define to 1 if you have the `EVP_CIPHER_CTX_iv_noconst' function. */
#undef HAVE_EVP_CIPHER_CTX_IV_NOCONST
+/* Define to 1 if you have the `EVP_CIPHER_CTX_set_iv' function. */
+#undef HAVE_EVP_CIPHER_CTX_SET_IV
+
/* Define to 1 if you have the `EVP_DigestFinal_ex' function. */
#undef HAVE_EVP_DIGESTFINAL_EX
/* Define to 1 if you have the `EVP_DigestInit_ex' function. */
#undef HAVE_EVP_DIGESTINIT_EX
/* Define to 1 if you have the `EVP_MD_CTX_cleanup' function. */
#undef HAVE_EVP_MD_CTX_CLEANUP
/* Define to 1 if you have the `EVP_MD_CTX_copy_ex' function. */
#undef HAVE_EVP_MD_CTX_COPY_EX
-/* Define if libcrypto has EVP_MD_CTX_free */
+/* Define to 1 if you have the `EVP_MD_CTX_free' function. */
#undef HAVE_EVP_MD_CTX_FREE
/* Define to 1 if you have the `EVP_MD_CTX_init' function. */
#undef HAVE_EVP_MD_CTX_INIT
-/* Define if libcrypto has EVP_MD_CTX_new */
+/* Define to 1 if you have the `EVP_MD_CTX_new' function. */
#undef HAVE_EVP_MD_CTX_NEW
-/* Define if libcrypto has EVP_PKEY_get0_RSA */
+/* Define to 1 if you have the `EVP_PKEY_get0_RSA' function. */
#undef HAVE_EVP_PKEY_GET0_RSA
/* Define to 1 if you have the `EVP_ripemd160' function. */
#undef HAVE_EVP_RIPEMD160
/* Define to 1 if you have the `EVP_sha256' function. */
#undef HAVE_EVP_SHA256
/* Define if you have ut_exit in utmp.h */
#undef HAVE_EXIT_IN_UTMP
/* Define to 1 if you have the `explicit_bzero' function. */
#undef HAVE_EXPLICIT_BZERO
/* Define to 1 if you have the `fchmod' function. */
#undef HAVE_FCHMOD
+/* Define to 1 if you have the `fchmodat' function. */
+#undef HAVE_FCHMODAT
+
/* Define to 1 if you have the `fchown' function. */
#undef HAVE_FCHOWN
+/* Define to 1 if you have the `fchownat' function. */
+#undef HAVE_FCHOWNAT
+
/* Use F_CLOSEM fcntl for closefrom */
#undef HAVE_FCNTL_CLOSEM
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if the system has the type `fd_mask'. */
#undef HAVE_FD_MASK
/* Define to 1 if you have the <features.h> header file. */
#undef HAVE_FEATURES_H
/* Define to 1 if you have the <floatingpoint.h> header file. */
#undef HAVE_FLOATINGPOINT_H
/* Define to 1 if you have the `flock' function. */
#undef HAVE_FLOCK
/* Define to 1 if you have the `fmt_scaled' function. */
#undef HAVE_FMT_SCALED
/* Define to 1 if you have the `freeaddrinfo' function. */
#undef HAVE_FREEADDRINFO
/* Define to 1 if you have the `freezero' function. */
#undef HAVE_FREEZERO
/* Define to 1 if the system has the type `fsblkcnt_t'. */
#undef HAVE_FSBLKCNT_T
/* Define to 1 if the system has the type `fsfilcnt_t'. */
#undef HAVE_FSFILCNT_T
/* Define to 1 if you have the `fstatfs' function. */
#undef HAVE_FSTATFS
/* Define to 1 if you have the `fstatvfs' function. */
#undef HAVE_FSTATVFS
/* Define to 1 if you have the `futimes' function. */
#undef HAVE_FUTIMES
/* Define to 1 if you have the `gai_strerror' function. */
#undef HAVE_GAI_STRERROR
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
/* Define to 1 if you have the `getaudit' function. */
#undef HAVE_GETAUDIT
/* Define to 1 if you have the `getaudit_addr' function. */
#undef HAVE_GETAUDIT_ADDR
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
/* Define to 1 if you have the `getgrouplist' function. */
#undef HAVE_GETGROUPLIST
/* Define to 1 if you have the `getgrset' function. */
#undef HAVE_GETGRSET
/* Define to 1 if you have the `getlastlogxbyname' function. */
#undef HAVE_GETLASTLOGXBYNAME
/* Define to 1 if you have the `getline' function. */
#undef HAVE_GETLINE
/* Define to 1 if you have the `getluid' function. */
#undef HAVE_GETLUID
/* Define to 1 if you have the `getnameinfo' function. */
#undef HAVE_GETNAMEINFO
/* Define to 1 if you have the `getopt' function. */
#undef HAVE_GETOPT
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define if your getopt(3) defines and uses optreset */
#undef HAVE_GETOPT_OPTRESET
/* Define if your libraries define getpagesize() */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the `getpeereid' function. */
#undef HAVE_GETPEEREID
/* Define to 1 if you have the `getpeerucred' function. */
#undef HAVE_GETPEERUCRED
/* Define to 1 if you have the `getpgid' function. */
#undef HAVE_GETPGID
/* Define to 1 if you have the `getpgrp' function. */
#undef HAVE_GETPGRP
/* Define to 1 if you have the `getpwanam' function. */
#undef HAVE_GETPWANAM
/* Define to 1 if you have the `getrandom' function. */
#undef HAVE_GETRANDOM
/* Define to 1 if you have the `getrlimit' function. */
#undef HAVE_GETRLIMIT
/* Define if getrrsetbyname() exists */
#undef HAVE_GETRRSETBYNAME
/* Define to 1 if you have the `getseuserbyname' function. */
#undef HAVE_GETSEUSERBYNAME
/* Define to 1 if you have the `getsid' function. */
#undef HAVE_GETSID
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the `getttyent' function. */
#undef HAVE_GETTTYENT
/* Define to 1 if you have the `getutent' function. */
#undef HAVE_GETUTENT
/* Define to 1 if you have the `getutid' function. */
#undef HAVE_GETUTID
/* Define to 1 if you have the `getutline' function. */
#undef HAVE_GETUTLINE
/* Define to 1 if you have the `getutxent' function. */
#undef HAVE_GETUTXENT
/* Define to 1 if you have the `getutxid' function. */
#undef HAVE_GETUTXID
/* Define to 1 if you have the `getutxline' function. */
#undef HAVE_GETUTXLINE
/* Define to 1 if you have the `getutxuser' function. */
#undef HAVE_GETUTXUSER
/* Define to 1 if you have the `get_default_context_with_level' function. */
#undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
/* Define to 1 if you have the `glob' function. */
#undef HAVE_GLOB
/* Define to 1 if you have the <glob.h> header file. */
#undef HAVE_GLOB_H
/* Define to 1 if you have the `group_from_gid' function. */
#undef HAVE_GROUP_FROM_GID
/* Define to 1 if you have the <gssapi_generic.h> header file. */
#undef HAVE_GSSAPI_GENERIC_H
/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_H
/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_KRB5_H
/* Define to 1 if you have the <gssapi.h> header file. */
#undef HAVE_GSSAPI_H
/* Define to 1 if you have the <gssapi_krb5.h> header file. */
#undef HAVE_GSSAPI_KRB5_H
/* Define if HEADER.ad exists in arpa/nameser.h */
#undef HAVE_HEADER_AD
/* Define to 1 if you have the `HMAC_CTX_init' function. */
#undef HAVE_HMAC_CTX_INIT
/* Define if you have ut_host in utmp.h */
#undef HAVE_HOST_IN_UTMP
/* Define if you have ut_host in utmpx.h */
#undef HAVE_HOST_IN_UTMPX
/* Define to 1 if you have the <iaf.h> header file. */
#undef HAVE_IAF_H
/* Define to 1 if you have the <ia.h> header file. */
#undef HAVE_IA_H
/* Define if you have ut_id in utmp.h */
#undef HAVE_ID_IN_UTMP
/* Define if you have ut_id in utmpx.h */
#undef HAVE_ID_IN_UTMPX
/* Define to 1 if you have the <ifaddrs.h> header file. */
#undef HAVE_IFADDRS_H
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
/* Define to 1 if you have the `inet_ntoa' function. */
#undef HAVE_INET_NTOA
/* Define to 1 if you have the `inet_ntop' function. */
#undef HAVE_INET_NTOP
/* Define to 1 if you have the `innetgr' function. */
#undef HAVE_INNETGR
/* define if you have int64_t data type */
#undef HAVE_INT64_T
/* Define to 1 if the system has the type `intmax_t'. */
#undef HAVE_INTMAX_T
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* define if you have intxx_t data type */
#undef HAVE_INTXX_T
/* Define to 1 if the system has the type `in_addr_t'. */
#undef HAVE_IN_ADDR_T
/* Define to 1 if the system has the type `in_port_t'. */
#undef HAVE_IN_PORT_T
/* Define if you have isblank(3C). */
#undef HAVE_ISBLANK
/* Define to 1 if you have the `krb5_cc_new_unique' function. */
#undef HAVE_KRB5_CC_NEW_UNIQUE
/* Define to 1 if you have the `krb5_free_error_message' function. */
#undef HAVE_KRB5_FREE_ERROR_MESSAGE
/* Define to 1 if you have the `krb5_get_error_message' function. */
#undef HAVE_KRB5_GET_ERROR_MESSAGE
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <lastlog.h> header file. */
#undef HAVE_LASTLOG_H
/* Define if you want ldns support */
#undef HAVE_LDNS
/* Define to 1 if you have the <libaudit.h> header file. */
#undef HAVE_LIBAUDIT_H
/* Define to 1 if you have the `bsm' library (-lbsm). */
#undef HAVE_LIBBSM
/* Define to 1 if you have the `crypt' library (-lcrypt). */
#undef HAVE_LIBCRYPT
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the <libgen.h> header file. */
#undef HAVE_LIBGEN_H
/* Define if system has libiaf that supports set_id */
#undef HAVE_LIBIAF
/* Define to 1 if you have the `network' library (-lnetwork). */
#undef HAVE_LIBNETWORK
/* Define to 1 if you have the `pam' library (-lpam). */
#undef HAVE_LIBPAM
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the <libutil.h> header file. */
#undef HAVE_LIBUTIL_H
/* Define to 1 if you have the `xnet' library (-lxnet). */
#undef HAVE_LIBXNET
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the <linux/audit.h> header file. */
#undef HAVE_LINUX_AUDIT_H
/* Define to 1 if you have the <linux/filter.h> header file. */
#undef HAVE_LINUX_FILTER_H
/* Define to 1 if you have the <linux/if_tun.h> header file. */
#undef HAVE_LINUX_IF_TUN_H
/* Define to 1 if you have the <linux/seccomp.h> header file. */
#undef HAVE_LINUX_SECCOMP_H
/* Define to 1 if you have the `llabs' function. */
#undef HAVE_LLABS
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if you have the `login' function. */
#undef HAVE_LOGIN
/* Define to 1 if you have the <login_cap.h> header file. */
#undef HAVE_LOGIN_CAP_H
/* Define to 1 if you have the `login_getcapbool' function. */
#undef HAVE_LOGIN_GETCAPBOOL
/* Define to 1 if you have the <login.h> header file. */
#undef HAVE_LOGIN_H
/* Define to 1 if you have the `logout' function. */
#undef HAVE_LOGOUT
/* Define to 1 if you have the `logwtmp' function. */
#undef HAVE_LOGWTMP
/* Define to 1 if the system has the type `long double'. */
#undef HAVE_LONG_DOUBLE
/* Define to 1 if the system has the type `long long'. */
#undef HAVE_LONG_LONG
/* Define to 1 if you have the <maillock.h> header file. */
#undef HAVE_MAILLOCK_H
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
to 0 otherwise. */
#undef HAVE_MALLOC
/* Define to 1 if you have the `mblen' function. */
#undef HAVE_MBLEN
/* Define to 1 if you have the `mbtowc' function. */
#undef HAVE_MBTOWC
/* Define to 1 if you have the `md5_crypt' function. */
#undef HAVE_MD5_CRYPT
/* Define if you want to allow MD5 passwords */
#undef HAVE_MD5_PASSWORDS
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `memset_s' function. */
#undef HAVE_MEMSET_S
/* Define to 1 if you have the `mkdtemp' function. */
#undef HAVE_MKDTEMP
/* define if you have mode_t data type */
#undef HAVE_MODE_T
/* Some systems put nanosleep outside of libc */
#undef HAVE_NANOSLEEP
/* Define to 1 if you have the <ndir.h> header file. */
#undef HAVE_NDIR_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netgroup.h> header file. */
#undef HAVE_NETGROUP_H
/* Define to 1 if you have the <net/if_tun.h> header file. */
#undef HAVE_NET_IF_TUN_H
/* Define to 1 if you have the <net/route.h> header file. */
#undef HAVE_NET_ROUTE_H
/* Define if you are on NeXT */
#undef HAVE_NEXT
/* Define to 1 if you have the `ngetaddrinfo' function. */
#undef HAVE_NGETADDRINFO
/* Define to 1 if you have the `nl_langinfo' function. */
#undef HAVE_NL_LANGINFO
/* Define to 1 if you have the `nsleep' function. */
#undef HAVE_NSLEEP
/* Define to 1 if you have the `ogetaddrinfo' function. */
#undef HAVE_OGETADDRINFO
/* Define if you have an old version of PAM which takes only one argument to
pam_strerror */
#undef HAVE_OLD_PAM
/* Define to 1 if you have the `openlog_r' function. */
#undef HAVE_OPENLOG_R
/* Define to 1 if you have the `openpty' function. */
#undef HAVE_OPENPTY
-/* Define if your ssl headers are included with #include <openssl/header.h> */
-#undef HAVE_OPENSSL
+/* as a macro */
+#undef HAVE_OPENSSL_ADD_ALL_ALGORITHMS
+
+/* Define to 1 if you have the `OPENSSL_init_crypto' function. */
+#undef HAVE_OPENSSL_INIT_CRYPTO
+
+/* Define to 1 if you have the `OpenSSL_version' function. */
+#undef HAVE_OPENSSL_VERSION
+
+/* Define to 1 if you have the `OpenSSL_version_num' function. */
+#undef HAVE_OPENSSL_VERSION_NUM
/* Define if you have Digital Unix Security Integration Architecture */
#undef HAVE_OSF_SIA
/* Define to 1 if you have the `pam_getenvlist' function. */
#undef HAVE_PAM_GETENVLIST
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
#undef HAVE_PAM_PAM_APPL_H
/* Define to 1 if you have the `pam_putenv' function. */
#undef HAVE_PAM_PUTENV
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
/* Define if you have ut_pid in utmp.h */
#undef HAVE_PID_IN_UTMP
/* define if you have pid_t data type */
#undef HAVE_PID_T
/* Define to 1 if you have the `pledge' function. */
#undef HAVE_PLEDGE
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* Define to 1 if you have the <poll.h> header file. */
#undef HAVE_POLL_H
/* Define to 1 if you have the `prctl' function. */
#undef HAVE_PRCTL
/* Define to 1 if you have the `priv_basicset' function. */
#undef HAVE_PRIV_BASICSET
/* Define to 1 if you have the <priv.h> header file. */
#undef HAVE_PRIV_H
/* Define if you have /proc/$pid/fd */
#undef HAVE_PROC_PID
/* Define to 1 if you have the `pstat' function. */
#undef HAVE_PSTAT
/* Define to 1 if you have the <pty.h> header file. */
#undef HAVE_PTY_H
/* Define to 1 if you have the `pututline' function. */
#undef HAVE_PUTUTLINE
/* Define to 1 if you have the `pututxline' function. */
#undef HAVE_PUTUTXLINE
/* Define to 1 if you have the `raise' function. */
#undef HAVE_RAISE
/* Define to 1 if you have the `readpassphrase' function. */
#undef HAVE_READPASSPHRASE
/* Define to 1 if you have the <readpassphrase.h> header file. */
#undef HAVE_READPASSPHRASE_H
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#undef HAVE_REALLOC
/* Define to 1 if you have the `reallocarray' function. */
#undef HAVE_REALLOCARRAY
/* Define to 1 if you have the `realpath' function. */
#undef HAVE_REALPATH
/* Define to 1 if you have the `recallocarray' function. */
#undef HAVE_RECALLOCARRAY
/* Define to 1 if you have the `recvmsg' function. */
#undef HAVE_RECVMSG
/* sys/resource.h has RLIMIT_NPROC */
#undef HAVE_RLIMIT_NPROC
/* Define to 1 if you have the <rpc/types.h> header file. */
#undef HAVE_RPC_TYPES_H
/* Define to 1 if you have the `rresvport_af' function. */
#undef HAVE_RRESVPORT_AF
/* Define to 1 if you have the `RSA_generate_key_ex' function. */
#undef HAVE_RSA_GENERATE_KEY_EX
-/* Define if libcrypto has RSA_get0_crt_params */
+/* Define to 1 if you have the `RSA_get0_crt_params' function. */
#undef HAVE_RSA_GET0_CRT_PARAMS
-/* Define if libcrypto has RSA_get0_factors */
+/* Define to 1 if you have the `RSA_get0_factors' function. */
#undef HAVE_RSA_GET0_FACTORS
-/* Define if libcrypto has RSA_get0_key */
+/* Define to 1 if you have the `RSA_get0_key' function. */
#undef HAVE_RSA_GET0_KEY
/* Define to 1 if you have the `RSA_get_default_method' function. */
#undef HAVE_RSA_GET_DEFAULT_METHOD
-/* Define if libcrypto has RSA_meth_dup */
+/* Define to 1 if you have the `RSA_meth_dup' function. */
#undef HAVE_RSA_METH_DUP
-/* Define if libcrypto has RSA_meth_free */
+/* Define to 1 if you have the `RSA_meth_free' function. */
#undef HAVE_RSA_METH_FREE
-/* Define if libcrypto has RSA_meth_get_finish */
+/* Define to 1 if you have the `RSA_meth_get_finish' function. */
#undef HAVE_RSA_METH_GET_FINISH
-/* Define if libcrypto has RSA_meth_set1_name */
+/* Define to 1 if you have the `RSA_meth_set1_name' function. */
#undef HAVE_RSA_METH_SET1_NAME
-/* Define if libcrypto has RSA_meth_set_finish */
+/* Define to 1 if you have the `RSA_meth_set_finish' function. */
#undef HAVE_RSA_METH_SET_FINISH
-/* Define if libcrypto has RSA_meth_set_priv_dec */
+/* Define to 1 if you have the `RSA_meth_set_priv_dec' function. */
#undef HAVE_RSA_METH_SET_PRIV_DEC
-/* Define if libcrypto has RSA_meth_set_priv_enc */
+/* Define to 1 if you have the `RSA_meth_set_priv_enc' function. */
#undef HAVE_RSA_METH_SET_PRIV_ENC
-/* Define if libcrypto has RSA_get0_srt_params */
+/* Define to 1 if you have the `RSA_set0_crt_params' function. */
#undef HAVE_RSA_SET0_CRT_PARAMS
-/* Define if libcrypto has RSA_set0_factors */
+/* Define to 1 if you have the `RSA_set0_factors' function. */
#undef HAVE_RSA_SET0_FACTORS
-/* Define if libcrypto has RSA_set0_key */
+/* Define to 1 if you have the `RSA_set0_key' function. */
#undef HAVE_RSA_SET0_KEY
/* Define to 1 if you have the <sandbox.h> header file. */
#undef HAVE_SANDBOX_H
/* Define to 1 if you have the `sandbox_init' function. */
#undef HAVE_SANDBOX_INIT
/* define if you have sa_family_t data type */
#undef HAVE_SA_FAMILY_T
/* Define to 1 if you have the `scan_scaled' function. */
#undef HAVE_SCAN_SCALED
/* Define if you have SecureWare-based protected password database */
#undef HAVE_SECUREWARE
/* Define to 1 if you have the <security/pam_appl.h> header file. */
#undef HAVE_SECURITY_PAM_APPL_H
/* Define to 1 if you have the `sendmsg' function. */
#undef HAVE_SENDMSG
/* Define to 1 if you have the `setauthdb' function. */
#undef HAVE_SETAUTHDB
/* Define to 1 if you have the `setdtablesize' function. */
#undef HAVE_SETDTABLESIZE
/* Define to 1 if you have the `setegid' function. */
#undef HAVE_SETEGID
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the `seteuid' function. */
#undef HAVE_SETEUID
/* Define to 1 if you have the `setgroupent' function. */
#undef HAVE_SETGROUPENT
/* Define to 1 if you have the `setgroups' function. */
#undef HAVE_SETGROUPS
/* Define to 1 if you have the `setlinebuf' function. */
#undef HAVE_SETLINEBUF
/* Define to 1 if you have the `setlogin' function. */
#undef HAVE_SETLOGIN
/* Define to 1 if you have the `setluid' function. */
#undef HAVE_SETLUID
/* Define to 1 if you have the `setpassent' function. */
#undef HAVE_SETPASSENT
/* Define to 1 if you have the `setpcred' function. */
#undef HAVE_SETPCRED
/* Define to 1 if you have the `setpflags' function. */
#undef HAVE_SETPFLAGS
/* Define to 1 if you have the `setppriv' function. */
#undef HAVE_SETPPRIV
/* Define to 1 if you have the `setproctitle' function. */
#undef HAVE_SETPROCTITLE
/* Define to 1 if you have the `setregid' function. */
#undef HAVE_SETREGID
/* Define to 1 if you have the `setresgid' function. */
#undef HAVE_SETRESGID
/* Define to 1 if you have the `setresuid' function. */
#undef HAVE_SETRESUID
/* Define to 1 if you have the `setreuid' function. */
#undef HAVE_SETREUID
/* Define to 1 if you have the `setrlimit' function. */
#undef HAVE_SETRLIMIT
/* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID
/* Define to 1 if you have the `setutent' function. */
#undef HAVE_SETUTENT
/* Define to 1 if you have the `setutxdb' function. */
#undef HAVE_SETUTXDB
/* Define to 1 if you have the `setutxent' function. */
#undef HAVE_SETUTXENT
/* Define to 1 if you have the `setvbuf' function. */
#undef HAVE_SETVBUF
/* Define to 1 if you have the `set_id' function. */
#undef HAVE_SET_ID
/* Define to 1 if you have the `SHA256_Update' function. */
#undef HAVE_SHA256_UPDATE
/* Define to 1 if you have the <sha2.h> header file. */
#undef HAVE_SHA2_H
/* Define to 1 if you have the <shadow.h> header file. */
#undef HAVE_SHADOW_H
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `sigvec' function. */
#undef HAVE_SIGVEC
/* Define to 1 if the system has the type `sig_atomic_t'. */
#undef HAVE_SIG_ATOMIC_T
/* define if you have size_t data type */
#undef HAVE_SIZE_T
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the `socketpair' function. */
#undef HAVE_SOCKETPAIR
/* Have PEERCRED socket option */
#undef HAVE_SO_PEERCRED
/* define if you have ssize_t data type */
#undef HAVE_SSIZE_T
/* Fields in struct sockaddr_storage */
#undef HAVE_SS_FAMILY_IN_SS
/* Define to 1 if you have the `statfs' function. */
#undef HAVE_STATFS
/* Define to 1 if you have the `statvfs' function. */
#undef HAVE_STATVFS
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasestr' function. */
#undef HAVE_STRCASESTR
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the `strftime' function. */
#undef HAVE_STRFTIME
/* Silly mkstemp() */
#undef HAVE_STRICT_MKSTEMP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcat' function. */
#undef HAVE_STRLCAT
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the `strmode' function. */
#undef HAVE_STRMODE
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define to 1 if you have the `strnlen' function. */
#undef HAVE_STRNLEN
/* Define to 1 if you have the `strnvis' function. */
#undef HAVE_STRNVIS
/* Define to 1 if you have the `strptime' function. */
#undef HAVE_STRPTIME
/* Define to 1 if you have the `strsep' function. */
#undef HAVE_STRSEP
/* Define to 1 if you have the `strsignal' function. */
#undef HAVE_STRSIGNAL
/* Define to 1 if you have the `strtoll' function. */
#undef HAVE_STRTOLL
/* Define to 1 if you have the `strtonum' function. */
#undef HAVE_STRTONUM
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define to 1 if you have the `strtoull' function. */
#undef HAVE_STRTOULL
/* define if you have struct addrinfo data type */
#undef HAVE_STRUCT_ADDRINFO
/* define if you have struct in6_addr data type */
#undef HAVE_STRUCT_IN6_ADDR
/* Define to 1 if `pw_change' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_CHANGE
/* Define to 1 if `pw_class' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_CLASS
/* Define to 1 if `pw_expire' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_EXPIRE
/* Define to 1 if `pw_gecos' is a member of `struct passwd'. */
#undef HAVE_STRUCT_PASSWD_PW_GECOS
/* define if you have struct sockaddr_in6 data type */
#undef HAVE_STRUCT_SOCKADDR_IN6
/* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */
#undef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
/* define if you have struct sockaddr_storage data type */
#undef HAVE_STRUCT_SOCKADDR_STORAGE
/* Define to 1 if `f_flags' is a member of `struct statfs'. */
#undef HAVE_STRUCT_STATFS_F_FLAGS
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
/* Define to 1 if `st_mtim' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIM
/* Define to 1 if `st_mtime' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIME
/* Define to 1 if the system has the type `struct timespec'. */
#undef HAVE_STRUCT_TIMESPEC
/* define if you have struct timeval */
#undef HAVE_STRUCT_TIMEVAL
/* Define to 1 if you have the `swap32' function. */
#undef HAVE_SWAP32
/* Define to 1 if you have the `sysconf' function. */
#undef HAVE_SYSCONF
/* Define if you have syslen in utmpx.h */
#undef HAVE_SYSLEN_IN_UTMPX
/* Define to 1 if you have the <sys/audit.h> header file. */
#undef HAVE_SYS_AUDIT_H
/* Define to 1 if you have the <sys/bitypes.h> header file. */
#undef HAVE_SYS_BITYPES_H
/* Define to 1 if you have the <sys/bsdtty.h> header file. */
#undef HAVE_SYS_BSDTTY_H
/* Define to 1 if you have the <sys/capsicum.h> header file. */
#undef HAVE_SYS_CAPSICUM_H
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
/* Define to 1 if you have the <sys/dir.h> header file. */
#undef HAVE_SYS_DIR_H
/* Define if your system defines sys_errlist[] */
#undef HAVE_SYS_ERRLIST
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define to 1 if you have the <sys/label.h> header file. */
#undef HAVE_SYS_LABEL_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/mount.h> header file. */
#undef HAVE_SYS_MOUNT_H
/* Define to 1 if you have the <sys/ndir.h> header file. */
#undef HAVE_SYS_NDIR_H
/* Define if your system defines sys_nerr */
#undef HAVE_SYS_NERR
/* Define to 1 if you have the <sys/poll.h> header file. */
#undef HAVE_SYS_POLL_H
/* Define to 1 if you have the <sys/prctl.h> header file. */
#undef HAVE_SYS_PRCTL_H
/* Define to 1 if you have the <sys/pstat.h> header file. */
#undef HAVE_SYS_PSTAT_H
/* Define to 1 if you have the <sys/ptms.h> header file. */
#undef HAVE_SYS_PTMS_H
/* Define to 1 if you have the <sys/ptrace.h> header file. */
#undef HAVE_SYS_PTRACE_H
/* Define to 1 if you have the <sys/random.h> header file. */
#undef HAVE_SYS_RANDOM_H
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define to 1 if you have the <sys/statvfs.h> header file. */
#undef HAVE_SYS_STATVFS_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/stream.h> header file. */
#undef HAVE_SYS_STREAM_H
/* Define to 1 if you have the <sys/stropts.h> header file. */
#undef HAVE_SYS_STROPTS_H
/* Define to 1 if you have the <sys/strtio.h> header file. */
#undef HAVE_SYS_STRTIO_H
/* Define to 1 if you have the <sys/sysctl.h> header file. */
#undef HAVE_SYS_SYSCTL_H
/* Force use of sys/syslog.h on Ultrix */
#undef HAVE_SYS_SYSLOG_H
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
#undef HAVE_SYS_SYSMACROS_H
/* Define to 1 if you have the <sys/timers.h> header file. */
#undef HAVE_SYS_TIMERS_H
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/un.h> header file. */
#undef HAVE_SYS_UN_H
/* Define to 1 if you have the <sys/vfs.h> header file. */
#undef HAVE_SYS_VFS_H
/* Define to 1 if you have the `tcgetpgrp' function. */
#undef HAVE_TCGETPGRP
/* Define to 1 if you have the `tcsendbreak' function. */
#undef HAVE_TCSENDBREAK
/* Define to 1 if you have the `time' function. */
#undef HAVE_TIME
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define if you have ut_time in utmp.h */
#undef HAVE_TIME_IN_UTMP
/* Define if you have ut_time in utmpx.h */
#undef HAVE_TIME_IN_UTMPX
/* Define to 1 if you have the `timingsafe_bcmp' function. */
#undef HAVE_TIMINGSAFE_BCMP
/* Define to 1 if you have the <tmpdir.h> header file. */
#undef HAVE_TMPDIR_H
/* Define to 1 if you have the `truncate' function. */
#undef HAVE_TRUNCATE
/* Define to 1 if you have the <ttyent.h> header file. */
#undef HAVE_TTYENT_H
/* Define if you have ut_tv in utmp.h */
#undef HAVE_TV_IN_UTMP
/* Define if you have ut_tv in utmpx.h */
#undef HAVE_TV_IN_UTMPX
/* Define if you have ut_type in utmp.h */
#undef HAVE_TYPE_IN_UTMP
/* Define if you have ut_type in utmpx.h */
#undef HAVE_TYPE_IN_UTMPX
/* Define to 1 if you have the <ucred.h> header file. */
#undef HAVE_UCRED_H
/* Define to 1 if the system has the type `uintmax_t'. */
#undef HAVE_UINTMAX_T
/* define if you have uintxx_t data type */
#undef HAVE_UINTXX_T
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV
/* Define to 1 if the system has the type `unsigned long long'. */
#undef HAVE_UNSIGNED_LONG_LONG
/* Define to 1 if you have the `updwtmp' function. */
#undef HAVE_UPDWTMP
/* Define to 1 if you have the `updwtmpx' function. */
#undef HAVE_UPDWTMPX
/* Define to 1 if you have the <usersec.h> header file. */
#undef HAVE_USERSEC_H
/* Define to 1 if you have the `user_from_uid' function. */
#undef HAVE_USER_FROM_UID
/* Define to 1 if you have the `usleep' function. */
#undef HAVE_USLEEP
/* Define to 1 if you have the <util.h> header file. */
#undef HAVE_UTIL_H
+/* Define to 1 if you have the `utimensat' function. */
+#undef HAVE_UTIMENSAT
+
/* Define to 1 if you have the `utimes' function. */
#undef HAVE_UTIMES
/* Define to 1 if you have the <utime.h> header file. */
#undef HAVE_UTIME_H
/* Define to 1 if you have the `utmpname' function. */
#undef HAVE_UTMPNAME
/* Define to 1 if you have the `utmpxname' function. */
#undef HAVE_UTMPXNAME
/* Define to 1 if you have the <utmpx.h> header file. */
#undef HAVE_UTMPX_H
/* Define to 1 if you have the <utmp.h> header file. */
#undef HAVE_UTMP_H
/* define if you have u_char data type */
#undef HAVE_U_CHAR
/* define if you have u_int data type */
#undef HAVE_U_INT
/* define if you have u_int64_t data type */
#undef HAVE_U_INT64_T
/* define if you have u_intxx_t data type */
#undef HAVE_U_INTXX_T
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Define if va_copy exists */
#undef HAVE_VA_COPY
/* Define to 1 if you have the <vis.h> header file. */
#undef HAVE_VIS_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
/* Define to 1 if you have the `warn' function. */
#undef HAVE_WARN
/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
/* Define to 1 if you have the `wcwidth' function. */
#undef HAVE_WCWIDTH
/* Define to 1 if you have the `_getlong' function. */
#undef HAVE__GETLONG
/* Define to 1 if you have the `_getpty' function. */
#undef HAVE__GETPTY
/* Define to 1 if you have the `_getshort' function. */
#undef HAVE__GETSHORT
/* Define if you have struct __res_state _res as an extern */
#undef HAVE__RES_EXTERN
/* Define to 1 if you have the `__b64_ntop' function. */
#undef HAVE___B64_NTOP
/* Define to 1 if you have the `__b64_pton' function. */
#undef HAVE___B64_PTON
/* Define if compiler implements __FUNCTION__ */
#undef HAVE___FUNCTION__
/* Define if libc defines __progname */
#undef HAVE___PROGNAME
/* Fields in struct sockaddr_storage */
#undef HAVE___SS_FAMILY_IN_SS
/* Define if __va_copy exists */
#undef HAVE___VA_COPY
/* Define if compiler implements __func__ */
#undef HAVE___func__
/* Define this if you are using the Heimdal version of Kerberos V5 */
#undef HEIMDAL
/* Define if you need to use IP address instead of hostname in $DISPLAY */
#undef IPADDR_IN_DISPLAY
/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
#undef IPV4_IN_IPV6
/* Define if your system choked on IP TOS setting */
#undef IP_TOS_IS_BROKEN
/* Define if you want Kerberos 5 support */
#undef KRB5
/* Define if pututxline updates lastlog too */
#undef LASTLOG_WRITE_PUTUTXLINE
/* Define to whatever link() returns for "not supported" if it doesn't return
EOPNOTSUPP. */
#undef LINK_OPNOTSUPP_ERRNO
/* Adjust Linux out-of-memory killer */
#undef LINUX_OOM_ADJUST
/* max value of long long calculated by configure */
#undef LLONG_MAX
/* min value of long long calculated by configure */
#undef LLONG_MIN
/* Account locked with pw(1) */
#undef LOCKED_PASSWD_PREFIX
/* String used in /etc/passwd to denote locked account */
#undef LOCKED_PASSWD_STRING
/* String used in /etc/passwd to denote locked account */
#undef LOCKED_PASSWD_SUBSTR
/* Some systems need a utmpx entry for /bin/login to work */
#undef LOGIN_NEEDS_UTMPX
/* Set this to your mail directory if you do not have _PATH_MAILDIR */
#undef MAIL_DIRECTORY
/* Need setpgrp to acquire controlling tty */
#undef NEED_SETPGRP
/* compiler does not accept __attribute__ on prototype args */
#undef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS
/* compiler does not accept __attribute__ on return types */
#undef NO_ATTRIBUTE_ON_RETURN_TYPE
/* Define to disable UID restoration test */
#undef NO_UID_RESTORATION_TEST
/* Define if X11 doesn't support AF_UNIX sockets on that system */
#undef NO_X11_UNIX_SOCKETS
/* Define if EVP_DigestUpdate returns void */
#undef OPENSSL_EVP_DIGESTUPDATE_VOID
/* OpenSSL has ECC */
#undef OPENSSL_HAS_ECC
/* libcrypto has NID_X9_62_prime256v1 */
#undef OPENSSL_HAS_NISTP256
/* libcrypto has NID_secp384r1 */
#undef OPENSSL_HAS_NISTP384
/* libcrypto has NID_secp521r1 */
#undef OPENSSL_HAS_NISTP521
/* libcrypto has EVP AES CTR */
#undef OPENSSL_HAVE_EVPCTR
/* libcrypto has EVP AES GCM */
#undef OPENSSL_HAVE_EVPGCM
/* libcrypto is missing AES 192 and 256 bit functions */
#undef OPENSSL_LOBOTOMISED_AES
/* Define if you want the OpenSSL internally seeded PRNG only */
#undef OPENSSL_PRNG_ONLY
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define if you are using Solaris-derived PAM which passes pam_messages to
the conversation function with an extra level of indirection */
#undef PAM_SUN_CODEBASE
/* Work around problematic Linux PAM modules handling of PAM_TTY */
#undef PAM_TTY_KLUDGE
/* must supply username to passwd */
#undef PASSWD_NEEDS_USERNAME
/* System dirs owned by bin (uid 2) */
#undef PLATFORM_SYS_DIR_UID
/* Port number of PRNGD/EGD random number socket */
#undef PRNGD_PORT
/* Location of PRNGD/EGD random number socket */
#undef PRNGD_SOCKET
/* read(1) can return 0 for a non-closed fd */
#undef PTY_ZEROREAD
/* Sandbox using capsicum */
#undef SANDBOX_CAPSICUM
/* Sandbox using Darwin sandbox_init(3) */
#undef SANDBOX_DARWIN
/* no privsep sandboxing */
#undef SANDBOX_NULL
/* Sandbox using pledge(2) */
#undef SANDBOX_PLEDGE
/* Sandbox using setrlimit(2) */
#undef SANDBOX_RLIMIT
/* Sandbox using seccomp filter */
#undef SANDBOX_SECCOMP_FILTER
/* setrlimit RLIMIT_FSIZE works */
#undef SANDBOX_SKIP_RLIMIT_FSIZE
/* define if setrlimit RLIMIT_NOFILE breaks things */
#undef SANDBOX_SKIP_RLIMIT_NOFILE
/* Sandbox using Solaris/Illumos privileges */
#undef SANDBOX_SOLARIS
/* Sandbox using systrace(4) */
#undef SANDBOX_SYSTRACE
/* Specify the system call convention in use */
#undef SECCOMP_AUDIT_ARCH
/* Define if your platform breaks doing a seteuid before a setuid */
#undef SETEUID_BREAKS_SETUID
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long int', as computed by sizeof. */
#undef SIZEOF_LONG_INT
/* The size of `long long int', as computed by sizeof. */
#undef SIZEOF_LONG_LONG_INT
/* The size of `short int', as computed by sizeof. */
#undef SIZEOF_SHORT_INT
/* Define as const if snprintf() can declare const char *fmt */
#undef SNPRINTF_CONST
/* Define to a Set Process Title type if your system is supported by
bsd-setproctitle.c */
#undef SPT_TYPE
/* Define if sshd somehow reacquires a controlling TTY after setsid() */
#undef SSHD_ACQUIRES_CTTY
/* sshd PAM service name */
#undef SSHD_PAM_SERVICE
/* Define if pam_chauthtok wants real uid set to the unpriv'ed user */
#undef SSHPAM_CHAUTHTOK_NEEDS_RUID
/* Use audit debugging module */
#undef SSH_AUDIT_EVENTS
/* Windows is sensitive to read buffer size */
#undef SSH_IOBUFSZ
/* non-privileged user for privilege separation */
#undef SSH_PRIVSEP_USER
/* Use tunnel device compatibility to OpenBSD */
#undef SSH_TUN_COMPAT_AF
/* Open tunnel devices the FreeBSD way */
#undef SSH_TUN_FREEBSD
/* Open tunnel devices the Linux tun/tap way */
#undef SSH_TUN_LINUX
/* No layer 2 tunnel support */
#undef SSH_TUN_NO_L2
/* Open tunnel devices the OpenBSD way */
#undef SSH_TUN_OPENBSD
/* Prepend the address family to IP tunnel traffic */
#undef SSH_TUN_PREPEND_AF
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you want a different $PATH for the superuser */
#undef SUPERUSER_PATH
/* syslog_r function is safe to use in in a signal handler */
#undef SYSLOG_R_SAFE_IN_SIGHAND
/* Support routing domains using Linux VRF */
#undef SYS_RDOMAIN_LINUX
/* Support passwords > 8 chars */
#undef UNIXWARE_LONG_PASSWORDS
/* Specify default $PATH */
#undef USER_PATH
/* Define this if you want to use libkafs' AFS support */
#undef USE_AFS
/* Use BSM audit module */
#undef USE_BSM_AUDIT
/* Use btmp to log bad logins */
#undef USE_BTMP
/* Use libedit for sftp */
#undef USE_LIBEDIT
/* Use Linux audit module */
#undef USE_LINUX_AUDIT
/* Enable OpenSSL engine support */
#undef USE_OPENSSL_ENGINE
/* Define if you want to enable PAM support */
#undef USE_PAM
/* Use PIPES instead of a socketpair() */
#undef USE_PIPES
/* Define if you have Solaris privileges */
#undef USE_SOLARIS_PRIVS
/* Define if you have Solaris process contracts */
#undef USE_SOLARIS_PROCESS_CONTRACTS
/* Define if you have Solaris projects */
#undef USE_SOLARIS_PROJECTS
/* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */
#undef WITH_ABBREV_NO_TTY
/* Define if you want to enable AIX4's authenticate function */
#undef WITH_AIXAUTHENTICATE
/* Define if you have/want arrays (cluster-wide session management, not C
arrays) */
#undef WITH_IRIX_ARRAY
/* Define if you want IRIX audit trails */
#undef WITH_IRIX_AUDIT
/* Define if you want IRIX kernel jobs */
#undef WITH_IRIX_JOBS
/* Define if you want IRIX project management */
#undef WITH_IRIX_PROJECT
/* use libcrypto for cryptography */
#undef WITH_OPENSSL
/* Define if you want SELinux support. */
#undef WITH_SELINUX
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define if xauth is found in your path */
#undef XAUTH_PATH
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* log for bad login attempts */
#undef _PATH_BTMP
/* Full path of your "passwd" program */
#undef _PATH_PASSWD_PROG
/* Specify location of ssh.pid */
#undef _PATH_SSH_PIDDIR
/* Define if we don't have struct __res_state in resolv.h */
#undef __res_state
/* Define to rpl_calloc if the replacement function should be used. */
#undef calloc
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to rpl_malloc if the replacement function should be used. */
#undef malloc
/* Define to rpl_realloc if the replacement function should be used. */
#undef realloc
/* type to use in place of socklen_t if not defined */
#undef socklen_t
diff --git a/configure b/configure
index 21a41103f91a..d276473cac11 100755
--- a/configure
+++ b/configure
@@ -1,22926 +1,20824 @@
#! /bin/sh
# From configure.ac Revision: 1.583 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for OpenSSH Portable.
#
# Report bugs to <openssh-unix-dev@mindrot.org>.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
&& (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='print -r --'
as_echo_n='print -rn --'
elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='printf %s\n'
as_echo_n='printf %s'
else
if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
as_echo_n='/usr/ucb/echo -n'
else
as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
as_echo_n_body='eval
arg=$1;
case $arg in #(
*"$as_nl"*)
expr "X$arg" : "X\\(.*\\)$as_nl";
arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
esac;
expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
'
export as_echo_n_body
as_echo_n='sh -c $as_echo_n_body as_echo'
fi
export as_echo_body
as_echo='sh -c $as_echo_body as_echo'
fi
# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
# IFS
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
$as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there. '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
&& ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '
# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
_as_can_reexec=no; export _as_can_reexec;
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
as_fn_exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
else
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
"
as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }
exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
else
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
if (eval "$as_required") 2>/dev/null; then :
as_have_required=yes
else
as_have_required=no
fi
if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
as_shell=$as_dir/$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
{ $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
CONFIG_SHELL=$as_shell as_have_required=yes
if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
break 2
fi
fi
done;;
esac
as_found=false
done
$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
{ $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
CONFIG_SHELL=$SHELL as_have_required=yes
fi; }
IFS=$as_save_IFS
if test "x$CONFIG_SHELL" != x; then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
if test x$as_have_required = xno; then :
$as_echo "$0: This script requires a shell more modern than all"
$as_echo "$0: the shells that I found on your system."
if test x${ZSH_VERSION+set} = xset ; then
$as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
else
$as_echo "$0: Please tell bug-autoconf@gnu.org and
$0: openssh-unix-dev@mindrot.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
fi
exit 1
fi
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS
## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
*\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
else
as_fn_append ()
{
eval $1=\$$1\$2
}
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
else
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
$as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
$as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
as_lineno_1=$LINENO as_lineno_1a=$LINENO
as_lineno_2=$LINENO as_lineno_2a=$LINENO
eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
# Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
sed -n '
p
/[$]LINENO/=
' <$as_myself |
sed '
s/[$]LINENO.*/&-/
t lineno
b
:lineno
N
:loop
s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
t loop
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
{ $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
# in an infinite loop. This has already happened in practice.
_as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
. "./$as_me.lineno"
# Exit status is that of the last command.
exit
}
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
test -n "$DJDIR" || exec 7<&0 </dev/null
exec 6>&1
# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='OpenSSH'
PACKAGE_TARNAME='openssh'
PACKAGE_VERSION='Portable'
PACKAGE_STRING='OpenSSH Portable'
PACKAGE_BUGREPORT='openssh-unix-dev@mindrot.org'
PACKAGE_URL=''
ac_unique_file="ssh.c"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
ac_subst_vars='LTLIBOBJS
DEPEND
UNSUPPORTED_ALGORITHMS
TEST_MALLOC_OPTIONS
TEST_SSH_UTF8
TEST_SSH_IPV6
piddir
user_path
mansubdir
MANTYPE
XAUTH_PATH
STRIP_OPT
xauth_path
PRIVSEP_PATH
K5LIBS
GSSLIBS
KRB5CONF
SSHDLIBS
SSHLIBS
SSH_PRIVSEP_USER
COMMENT_OUT_ECC
TEST_SSH_ECC
LIBEDIT
PKGCONFIG
LDNSCONFIG
LIBOBJS
LD
PATH_PASSWD_PROG
STARTUP_SCRIPT_SHELL
MAKE_PACKAGE_SUPPORTED
PATH_USERADD_PROG
PATH_GROUPADD_PROG
MANFMT
TEST_SHELL
MANDOC
NROFF
GROFF
SH
TEST_MINUS_S_SH
ENT
SED
KILL
CAT
ac_ct_AR
AR
MKDIR_P
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
RANLIB
AWK
EGREP
GREP
CPP
host_os
host_vendor
host_cpu
host
build_os
build_vendor
build_cpu
build
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_largefile
with_openssl
with_stackprotect
with_hardening
with_rpath
with_cflags
with_cflags_after
with_cppflags
with_ldflags
with_ldflags_after
with_libs
with_Werror
with_solaris_contracts
with_solaris_projects
with_solaris_privs
with_osfsia
with_zlib
with_zlib_version_check
with_ldns
with_libedit
with_audit
with_pie
enable_pkcs11
with_ssl_dir
with_openssl_header_check
with_ssl_engine
with_prngd_port
with_prngd_socket
with_pam
with_pam_service
with_privsep_user
with_sandbox
with_selinux
with_kerberos5
with_privsep_path
with_xauth
enable_strip
with_maildir
with_mantype
with_md5_passwords
with_shadow
with_ipaddr_display
enable_etc_default_login
with_default_path
with_superuser_path
with_4in6
with_bsd_auth
with_pid_dir
enable_lastlog
enable_utmp
enable_utmpx
enable_wtmp
enable_wtmpx
enable_libutil
enable_pututline
enable_pututxline
with_lastlog
'
ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS
CPP'
# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE
# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'
ac_prev=
ac_dashdash=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval $ac_prev=\$ac_option
ac_prev=
continue
fi
case $ac_option in
*=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
*=) ac_optarg= ;;
*) ac_optarg=yes ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file=$ac_optarg ;;
--config-cache | -C)
cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=*)
datadir=$ac_optarg ;;
-datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
| --dataroo | --dataro | --datar)
ac_prev=datarootdir ;;
-datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
| --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
datarootdir=$ac_optarg ;;
-disable-* | --disable-*)
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=no ;;
-docdir | --docdir | --docdi | --doc | --do)
ac_prev=docdir ;;
-docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
docdir=$ac_optarg ;;
-dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
ac_prev=dvidir ;;
-dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
dvidir=$ac_optarg ;;
-enable-* | --enable-*)
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid feature name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
-help | --help | --hel | --he | -h)
ac_init_help=long ;;
-help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
ac_init_help=recursive ;;
-help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
ac_init_help=short ;;
-host | --host | --hos | --ho)
ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
host_alias=$ac_optarg ;;
-htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
ac_prev=htmldir ;;
-htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
| --ht=*)
htmldir=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir=$ac_optarg ;;
-localedir | --localedir | --localedi | --localed | --locale)
ac_prev=localedir ;;
-localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
localedir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst | --locals)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name=$ac_optarg ;;
-pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
ac_prev=pdfdir ;;
-pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
pdfdir=$ac_optarg ;;
-psdir | --psdir | --psdi | --psd | --ps)
ac_prev=psdir ;;
-psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
psdir=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
-version | --version | --versio | --versi | --vers | -V)
ac_init_version=: ;;
-with-* | --with-*)
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=\$ac_optarg ;;
-without-* | --without-*)
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
as_fn_error $? "invalid package name: $ac_useropt"
ac_useropt_orig=$ac_useropt
ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=no ;;
--x)
# Obsolete; use --with-x.
with_x=yes ;;
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
-*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
;;
*=*)
ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
*)
# FIXME: should be removed in autoconf 3.0.
$as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
$as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
*) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
# Check all directory arguments for consistency.
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
libdir localedir mandir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
case $ac_val in
*/ )
ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
eval $ac_var=\$ac_val;;
esac
# Be sure to have absolute directory names.
case $ac_val in
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias
# FIXME: To remove some day.
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
fi
ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-
test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then the parent directory.
ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r "$srcdir/$ac_unique_file"; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
case $srcdir in
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
esac
for ac_var in $ac_precious_vars; do
eval ac_env_${ac_var}_set=\${${ac_var}+set}
eval ac_env_${ac_var}_value=\$${ac_var}
eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
eval ac_cv_env_${ac_var}_value=\$${ac_var}
done
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures OpenSSH Portable to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
-q, --quiet, --silent do not print \`checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for \`--cache-file=config.cache'
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or \`..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/openssh]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
_ACEOF
cat <<\_ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of OpenSSH Portable:";;
esac
cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-largefile omit support for large files
--disable-pkcs11 disable PKCS#11 support code [no]
--disable-strip Disable calling strip(1) on install
--disable-etc-default-login Disable using PATH from /etc/default/login no
--disable-lastlog disable use of lastlog even if detected no
--disable-utmp disable use of utmp even if detected no
--disable-utmpx disable use of utmpx even if detected no
--disable-wtmp disable use of wtmp even if detected no
--disable-wtmpx disable use of wtmpx even if detected no
--disable-libutil disable use of libutil (login() etc.) no
--disable-pututline disable use of pututline() etc. (uwtmp) no
--disable-pututxline disable use of pututxline() etc. (uwtmpx) no
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL**
--without-stackprotect Don't use compiler's stack protection
--without-hardening Don't use toolchain hardening flags
--without-rpath Disable auto-added -R linker paths
--with-cflags Specify additional flags to pass to compiler
--with-cflags-after Specify additional flags to pass to compiler after configure
--with-cppflags Specify additional flags to pass to preprocessor
--with-ldflags Specify additional flags to pass to linker
--with-ldflags-after Specify additional flags to pass to linker after configure
--with-libs Specify additional libraries to link with
--with-Werror Build main code with -Werror
--with-solaris-contracts Enable Solaris process contracts (experimental)
--with-solaris-projects Enable Solaris projects (experimental)
--with-solaris-privs Enable Solaris/Illumos privileges (experimental)
--with-osfsia Enable Digital Unix SIA
--with-zlib=PATH Use zlib in PATH
--without-zlib-version-check Disable zlib version check
--with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH)
--with-libedit[=PATH] Enable libedit support for sftp
--with-audit=module Enable audit support (modules=debug,bsm,linux)
--with-pie Build Position Independent Executables if possible
--with-ssl-dir=PATH Specify path to OpenSSL installation
--without-openssl-header-check Disable OpenSSL version consistency check
--with-ssl-engine Enable OpenSSL (hardware) ENGINE support
--with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT
--with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)
--with-pam Enable PAM support
--with-pam-service=name Specify PAM service name
--with-privsep-user=user Specify non-privileged user for privilege separation
--with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter, systrace, pledge)
--with-selinux Enable SELinux support
--with-kerberos5=PATH Enable Kerberos 5 support
--with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)
--with-xauth=PATH Specify path to xauth program
--with-maildir=/path/to/mail Specify your system mail directory
--with-mantype=man|cat|doc Set man page type
--with-md5-passwords Enable use of MD5 passwords
--without-shadow Disable shadow password support
--with-ipaddr-display Use ip address instead of hostname in $DISPLAY
--with-default-path= Specify default $PATH environment for server
--with-superuser-path= Specify different path for super-user
--with-4in6 Check for and convert IPv4 in IPv6 mapped addresses
--with-bsd-auth Enable BSD auth support
--with-pid-dir=PATH Specify location of sshd.pid file
--with-lastlog=FILE|DIR specify lastlog location common locations
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to <openssh-unix-dev@mindrot.org>.
_ACEOF
ac_status=$?
fi
if test "$ac_init_help" = "recursive"; then
# If there are subdirs, report their specific --help.
for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
test -d "$ac_dir" ||
{ cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
continue
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
# Check for guested configure.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
elif test -f "$ac_srcdir/configure"; then
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
OpenSSH configure Portable
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
exit
fi
## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_compile
# ac_fn_c_try_run LINENO
# ----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
# that executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then :
ac_retval=0
else
$as_echo "$as_me: program exited with status $ac_status" >&5
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_run
# ac_fn_c_try_cpp LINENO
# ----------------------
# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_cpp ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } > conftest.i && {
test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
test ! -s conftest.err
}; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_cpp
# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists and can be compiled using the include files in
# INCLUDES, setting the cache variable VAR accordingly.
ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_compile
# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
# ---------------------------------------------
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
# accordingly.
ac_fn_c_check_decl ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
as_decl_name=`echo $2|sed 's/ *(.*//'`
as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
#ifndef $as_decl_name
#ifdef __cplusplus
(void) $as_decl_use;
#else
(void) $as_decl_name;
#endif
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_decl
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_link ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
rm -f conftest.$ac_objext conftest$ac_exeext
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
test -x conftest$ac_exeext
}; then :
ac_retval=0
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
# Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
# created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
# interfere with the next link command; also delete a directory that is
# left behind by Apple's compiler. We do this before executing the actions.
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_link
# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
# Tests whether HEADER exists, giving a warning if it cannot be compiled using
# the include files in INCLUDES and setting the cache variable VAR
# accordingly.
ac_fn_c_check_header_mongrel ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if eval \${$3+:} false; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
else
# Is the header compilable?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
$as_echo_n "checking $2 usability... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_header_compiler=yes
else
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
$as_echo "$ac_header_compiler" >&6; }
# Is the header present?
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
$as_echo_n "checking $2 presence... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <$2>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
ac_header_preproc=yes
else
ac_header_preproc=no
fi
rm -f conftest.err conftest.i conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
$as_echo "$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
yes:no: )
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
;;
no:yes:* )
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
( $as_echo "## ------------------------------------------- ##
## Report this to openssh-unix-dev@mindrot.org ##
## ------------------------------------------- ##"
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=\$ac_header_compiler"
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_header_mongrel
# ac_fn_c_check_func LINENO FUNC VAR
# ----------------------------------
# Tests whether FUNC exists, setting the cache variable VAR accordingly
ac_fn_c_check_func ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
For example, HP-UX 11i <limits.h> declares gettimeofday. */
#define $2 innocuous_$2
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $2 (); below.
Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
<limits.h> exists even on freestanding compilers. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
#undef $2
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char $2 ();
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined __stub_$2 || defined __stub___$2
choke me
#endif
int
main ()
{
return $2 ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
eval "$3=yes"
else
eval "$3=no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_func
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
$as_echo_n "checking for $2... " >&6; }
if eval \${$3+:} false; then :
$as_echo_n "(cached) " >&6
else
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
if (sizeof ($2))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
if (sizeof (($2)))
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
else
eval "$3=yes"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$3
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
# --------------------------------------------
# Tries to find the compile-time value of EXPR in a program that includes
# INCLUDES, setting VAR accordingly. Returns whether the value could be
# computed
ac_fn_c_compute_int ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if test "$cross_compiling" = yes; then
# Depending upon the size, compute the lo and hi bounds.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) >= 0)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_lo=0 ac_mid=0
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_hi=$ac_mid; break
else
as_fn_arith $ac_mid + 1 && ac_lo=$as_val
if test $ac_lo -le $ac_mid; then
ac_lo= ac_hi=
break
fi
as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) < 0)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_lo=$ac_mid; break
else
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
break
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
else
ac_lo= ac_hi=
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
main ()
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_hi=$ac_mid
else
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
'') ac_retval=1 ;;
esac
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
static long int longval () { return $2; }
static unsigned long int ulongval () { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
FILE *f = fopen ("conftest.val", "w");
if (! f)
return 1;
if (($2) < 0)
{
long int i = longval ();
if (i != ($2))
return 1;
fprintf (f, "%ld", i);
}
else
{
unsigned long int i = ulongval ();
if (i != ($2))
return 1;
fprintf (f, "%lu", i);
}
/* Do not output a trailing newline, as this causes \r\n confusion
on some platforms. */
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
else
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
rm -f conftest.val
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
# ----------------------------------------------------
# Tries to find if the field MEMBER exists in type AGGR, after including
# INCLUDES, setting cache variable VAR accordingly.
ac_fn_c_check_member ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
$as_echo_n "checking for $2.$3... " >&6; }
if eval \${$4+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
main ()
{
static $2 ac_aggr;
if (ac_aggr.$3)
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$4=yes"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$5
int
main ()
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
eval "$4=yes"
else
eval "$4=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
eval ac_res=\$$4
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_member
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by OpenSSH $as_me Portable, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##
hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
_ASUNAME
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
$as_echo "PATH: $as_dir"
done
IFS=$as_save_IFS
} >&5
cat >&5 <<_ACEOF
## ----------- ##
## Core tests. ##
## ----------- ##
_ACEOF
# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_must_keep_next=false
for ac_pass in 1 2
do
for ac_arg
do
case $ac_arg in
-no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
2)
as_fn_append ac_configure_args1 " '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
case $ac_arg in
*=* | --config-cache | -C | -disable-* | --disable-* \
| -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
| -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
| -with-* | --with-* | -without-* | --without-* | --x)
case "$ac_configure_args0 " in
"$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
esac
;;
-* ) ac_must_keep_next=true ;;
esac
fi
as_fn_append ac_configure_args " '$ac_arg'"
;;
esac
done
done
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}
# When interrupted or exit'd, cleanup temporary files, and complete
# config.log. We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
# Save into config.log some information that might help in debugging.
{
echo
$as_echo "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
*_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
sed -n \
"s/'\''/'\''\\\\'\'''\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
;; #(
*)
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
)
echo
$as_echo "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
eval ac_val=\$$ac_var
case $ac_val in
*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
$as_echo "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
$as_echo "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
eval ac_val=\$$ac_var
case $ac_val in
*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
$as_echo "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
$as_echo "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
cat confdefs.h
echo
fi
test "$ac_signal" != 0 &&
$as_echo "$as_me: caught signal $ac_signal"
$as_echo "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
$as_echo "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
cat >>confdefs.h <<_ACEOF
#define PACKAGE_NAME "$PACKAGE_NAME"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION "$PACKAGE_VERSION"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_STRING "$PACKAGE_STRING"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
_ACEOF
cat >>confdefs.h <<_ACEOF
#define PACKAGE_URL "$PACKAGE_URL"
_ACEOF
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
ac_site_file1=NONE
ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
# We do not want a PATH search for config.site.
case $CONFIG_SITE in #((
-*) ac_site_file1=./$CONFIG_SITE;;
*/*) ac_site_file1=$CONFIG_SITE;;
*) ac_site_file1=./$CONFIG_SITE;;
esac
elif test "x$prefix" != xNONE; then
ac_site_file1=$prefix/share/config.site
ac_site_file2=$prefix/etc/config.site
else
ac_site_file1=$ac_default_prefix/share/config.site
ac_site_file2=$ac_default_prefix/etc/config.site
fi
for ac_site_file in "$ac_site_file1" "$ac_site_file2"
do
test "x$ac_site_file" = xNONE && continue
if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
$as_echo "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
|| { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
done
if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
$as_echo "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
$as_echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
for ac_var in $ac_precious_vars; do
eval ac_old_set=\$ac_cv_env_${ac_var}_set
eval ac_new_set=\$ac_env_${ac_var}_set
eval ac_old_val=\$ac_cv_env_${ac_var}_value
eval ac_new_val=\$ac_env_${ac_var}_value
case $ac_old_set,$ac_new_set in
set,)
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
ac_cache_corrupted=: ;;
,set)
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
ac_cache_corrupted=: ;;
,);;
*)
if test "x$ac_old_val" != "x$ac_new_val"; then
# differences in whitespace do not lead to failure.
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
*\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
*" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
*) as_fn_append ac_configure_args " '$ac_arg'" ;;
esac
fi
done
if $ac_cache_corrupted; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_config_headers="$ac_config_headers config.h"
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- fi
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl.exe
+ for ac_prog in cc gcc
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
- for ac_prog in cl.exe
+ for ac_prog in cc gcc
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
$as_echo "$ac_ct_CC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$ac_ct_CC" && break
done
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
fi
-fi
-
test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
sed '10a\
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
$as_echo_n "checking whether the C compiler works... " >&6; }
ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
ac_rmfiles=
for ac_file in $ac_files
do
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
* ) ac_rmfiles="$ac_rmfiles $ac_file";;
esac
done
rm -f $ac_rmfiles
if { { ac_try="$ac_link_default"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
;;
[ab].out )
# We found the default executable, but exeext='' is most
# certainly right.
break;;
*.* )
if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
# We set ac_cv_exeext here because the later test for it is not
# safe: cross compilers may not add the suffix if given an `-o'
# argument, so we may need to know it at that point already.
# Even if this section looks crufty: it has the advantage of
# actually working.
break;;
* )
break;;
esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
else
ac_file=''
fi
if test -z "$ac_file"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
$as_echo_n "checking for C compiler default output file name... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
$as_echo "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
$as_echo_n "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
for ac_file in conftest.exe conftest conftest.*; do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
*.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
break;;
* ) break;;
esac
done
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
$as_echo "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
$as_echo_n "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
$as_echo "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
$as_echo_n "checking for suffix of object files... " >&6; }
if ${ac_cv_objext+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
$as_echo "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
if ${ac_cv_c_compiler_gnu+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
#ifndef __GNUC__
choke me
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_compiler_gnu=yes
else
ac_compiler_gnu=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
ac_test_CFLAGS=${CFLAGS+set}
ac_save_CFLAGS=$CFLAGS
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
$as_echo_n "checking whether $CC accepts -g... " >&6; }
if ${ac_cv_prog_cc_g+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
else
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
else
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_g=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
$as_echo "$ac_cv_prog_cc_g" >&6; }
if test "$ac_test_CFLAGS" = set; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
else
CFLAGS=
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
if ${ac_cv_prog_cc_c89+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_prog_cc_c89=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
#include <stdio.h>
struct stat;
/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
struct buf { int x; };
FILE * (*rcsopen) (struct buf *, struct stat *, int);
static char *e (p, i)
char **p;
int i;
{
return p[i];
}
static char *f (char * (*g) (char **, int), char **p, ...)
{
char *s;
va_list v;
va_start (v,p);
s = g (p, va_arg (v,int));
va_end (v);
return s;
}
/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
function prototypes and stuff, but not '\xHH' hex character constants.
These don't provoke an error unfortunately, instead are silently treated
as 'x'. The following induces an error, until -std is added to get
proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
array size at least. It's necessary to write '\x00'==0 to get something
that's true only with -std. */
int osf4_cc_array ['\x00' == 0 ? 1 : -1];
/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
inside strings and character constants. */
#define FOO(x) 'x'
int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
int test (int i, double x);
struct s1 {int (*f) (int a);};
struct s2 {int (*f) (double a);};
int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
int argc;
char **argv;
int
main ()
{
return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
;
return 0;
}
_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in
x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
xno)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
CC="$CC $ac_cv_prog_cc_c89"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
esac
if test "x$ac_cv_prog_cc_c89" != xno; then :
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
if test -f "$ac_dir/install-sh"; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install-sh -c"
break
elif test -f "$ac_dir/install.sh"; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install.sh -c"
break
elif test -f "$ac_dir/shtool"; then
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/shtool install -c"
break
fi
done
if test -z "$ac_aux_dir"; then
as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
fi
# These three variables are undocumented and unsupported,
# and are intended to be withdrawn in a future Autoconf release.
# They can cause serious problems if a builder's source tree is in a directory
# whose full name contains unusual characters.
ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
# Make sure we can run config.sub.
$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
$as_echo_n "checking build system type... " >&6; }
if ${ac_cv_build+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
$as_echo "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_build
shift
build_cpu=$1
build_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
build_os=$*
IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
$as_echo_n "checking host system type... " >&6; }
if ${ac_cv_host+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
$as_echo "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_host
shift
host_cpu=$1
host_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
host_os=$*
IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
$as_echo_n "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
if ${ac_cv_prog_CPP+:} false; then :
$as_echo_n "(cached) " >&6
else
# Double quotes because CPP needs to be expanded
for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
break
fi
done
ac_cv_prog_CPP=$CPP
fi
CPP=$ac_cv_prog_CPP
else
ac_cv_prog_CPP=$CPP
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
$as_echo "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
if ${ac_cv_path_GREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -z "$GREP"; then
ac_path_GREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in grep ggrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_GREP" || continue
# Check for GNU ac_path_GREP and select it if it is found.
# Check for GNU $ac_path_GREP
case `"$ac_path_GREP" --version 2>&1` in
*GNU*)
ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
*)
ac_count=0
$as_echo_n 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
$as_echo 'GREP' >> "conftest.nl"
"$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_GREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_GREP="$ac_path_GREP"
ac_path_GREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_GREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_GREP"; then
as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_GREP=$GREP
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
$as_echo "$ac_cv_path_GREP" >&6; }
GREP="$ac_cv_path_GREP"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if ${ac_cv_path_EGREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
then ac_cv_path_EGREP="$GREP -E"
else
if test -z "$EGREP"; then
ac_path_EGREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
*GNU*)
ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
*)
ac_count=0
$as_echo_n 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
$as_echo 'EGREP' >> "conftest.nl"
"$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP="$ac_path_EGREP"
ac_path_EGREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_EGREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
$as_echo "$ac_cv_path_EGREP" >&6; }
EGREP="$ac_cv_path_EGREP"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
$as_echo_n "checking for ANSI C header files... " >&6; }
if ${ac_cv_header_stdc+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_header_stdc=yes
else
ac_cv_header_stdc=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "memchr" >/dev/null 2>&1; then :
else
ac_cv_header_stdc=no
fi
rm -f conftest*
fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "free" >/dev/null 2>&1; then :
else
ac_cv_header_stdc=no
fi
rm -f conftest*
fi
if test $ac_cv_header_stdc = yes; then
# /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
if test "$cross_compiling" = yes; then :
:
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ctype.h>
#include <stdlib.h>
#if ((' ' & 0x0FF) == 0x020)
# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
#else
# define ISLOWER(c) \
(('a' <= (c) && (c) <= 'i') \
|| ('j' <= (c) && (c) <= 'r') \
|| ('s' <= (c) && (c) <= 'z'))
# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
#endif
#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
int
main ()
{
int i;
for (i = 0; i < 256; i++)
if (XOR (islower (i), ISLOWER (i))
|| toupper (i) != TOUPPER (i))
return 2;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
else
ac_cv_header_stdc=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
$as_echo "$ac_cv_header_stdc" >&6; }
if test $ac_cv_header_stdc = yes; then
$as_echo "#define STDC_HEADERS 1" >>confdefs.h
fi
# On IRIX 5.3, sys/types and inttypes.h are conflicting.
for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
inttypes.h stdint.h unistd.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
if ${ac_cv_c_bigendian+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_c_bigendian=unknown
# See if we're dealing with a universal compiler.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __APPLE_CC__
not a universal capable compiler
#endif
typedef int dummy;
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
# Check for potential -arch flags. It is not universal unless
# there are at least two -arch flags with different values.
ac_arch=
ac_prev=
for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
if test -n "$ac_prev"; then
case $ac_word in
i?86 | x86_64 | ppc | ppc64)
if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
ac_arch=$ac_word
else
ac_cv_c_bigendian=universal
break
fi
;;
esac
ac_prev=
elif test "x$ac_word" = "x-arch"; then
ac_prev=arch
fi
done
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test $ac_cv_c_bigendian = unknown; then
# See if sys/param.h defines the BYTE_ORDER macro.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/param.h>
int
main ()
{
#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
&& defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
&& LITTLE_ENDIAN)
bogus endian macros
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
# It does; now see whether it defined to BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/param.h>
int
main ()
{
#if BYTE_ORDER != BIG_ENDIAN
not big endian
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_c_bigendian=yes
else
ac_cv_c_bigendian=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
int
main ()
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
bogus endian macros
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
# It does; now see whether it defined to _BIG_ENDIAN or not.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
int
main ()
{
#ifndef _BIG_ENDIAN
not big endian
#endif
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_c_bigendian=yes
else
ac_cv_c_bigendian=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test $ac_cv_c_bigendian = unknown; then
# Compile a test program.
if test "$cross_compiling" = yes; then :
# Try to guess by grepping values from an object file.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
short int ascii_mm[] =
{ 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
short int ascii_ii[] =
{ 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
int use_ascii (int i) {
return ascii_mm[i] + ascii_ii[i];
}
short int ebcdic_ii[] =
{ 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
short int ebcdic_mm[] =
{ 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
int use_ebcdic (int i) {
return ebcdic_mm[i] + ebcdic_ii[i];
}
extern int foo;
int
main ()
{
return use_ascii (foo) == use_ebcdic (foo);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
ac_cv_c_bigendian=yes
fi
if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
if test "$ac_cv_c_bigendian" = unknown; then
ac_cv_c_bigendian=no
else
# finding both strings is unlikely to happen, but who knows?
ac_cv_c_bigendian=unknown
fi
fi
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
main ()
{
/* Are we little or big endian? From Harbison&Steele. */
union
{
long int l;
char c[sizeof (long int)];
} u;
u.l = 1;
return u.c[sizeof (long int) - 1] == 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_c_bigendian=no
else
ac_cv_c_bigendian=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
$as_echo "$ac_cv_c_bigendian" >&6; }
case $ac_cv_c_bigendian in #(
yes)
$as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
;; #(
no)
;; #(
universal)
$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
;; #(
*)
as_fn_error $? "unknown endianness
presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
esac
# Checks for programs.
for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_AWK+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$AWK"; then
ac_cv_prog_AWK="$AWK" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_AWK="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
AWK=$ac_cv_prog_AWK
if test -n "$AWK"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
$as_echo "$AWK" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$AWK" && break
done
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
$as_echo_n "checking how to run the C preprocessor... " >&6; }
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
if ${ac_cv_prog_CPP+:} false; then :
$as_echo_n "(cached) " >&6
else
# Double quotes because CPP needs to be expanded
for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
do
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
break
fi
done
ac_cv_prog_CPP=$CPP
fi
CPP=$ac_cv_prog_CPP
else
ac_cv_prog_CPP=$CPP
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
$as_echo "$CPP" >&6; }
ac_preproc_ok=false
for ac_c_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
Syntax error
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
else
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.i conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
if ac_fn_c_try_cpp "$LINENO"; then :
# Broken: success on invalid input.
continue
else
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.i conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.i conftest.err conftest.$ac_ext
if $ac_preproc_ok; then :
else
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
See \`config.log' for more details" "$LINENO" 5; }
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_RANLIB+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
$as_echo "$RANLIB" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
$as_echo "$ac_ct_RANLIB" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$ac_ct_RANLIB" = x; then
RANLIB=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
fi
else
RANLIB="$ac_cv_prog_RANLIB"
fi
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AmigaOS /C/install, which installs bootblocks on floppy discs
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
$as_echo_n "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
if ${ac_cv_path_install+:} false; then :
$as_echo_n "(cached) " >&6
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
# Account for people who put trailing slashes in PATH elements.
case $as_dir/ in #((
./ | .// | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
elif test $ac_prog = install &&
grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# program-specific install script used by HP pwplus--don't use.
:
else
rm -rf conftest.one conftest.two conftest.dir
echo one > conftest.one
echo two > conftest.two
mkdir conftest.dir
if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
test -s conftest.one && test -s conftest.two &&
test -s conftest.dir/conftest.one &&
test -s conftest.dir/conftest.two
then
ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
break 3
fi
fi
fi
done
done
;;
esac
done
IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
fi
if test "${ac_cv_path_install+set}" = set; then
INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. Don't cache a
# value for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
INSTALL=$ac_install_sh
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
$as_echo "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
$as_echo_n "checking for egrep... " >&6; }
if ${ac_cv_path_EGREP+:} false; then :
$as_echo_n "(cached) " >&6
else
if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
then ac_cv_path_EGREP="$GREP -E"
else
if test -z "$EGREP"; then
ac_path_EGREP_found=false
# Loop through the user's path and test for each of PROGNAME-LIST
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in egrep; do
for ac_exec_ext in '' $ac_executable_extensions; do
ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
as_fn_executable_p "$ac_path_EGREP" || continue
# Check for GNU ac_path_EGREP and select it if it is found.
# Check for GNU $ac_path_EGREP
case `"$ac_path_EGREP" --version 2>&1` in
*GNU*)
ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
*)
ac_count=0
$as_echo_n 0123456789 >"conftest.in"
while :
do
cat "conftest.in" "conftest.in" >"conftest.tmp"
mv "conftest.tmp" "conftest.in"
cp "conftest.in" "conftest.nl"
$as_echo 'EGREP' >> "conftest.nl"
"$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
as_fn_arith $ac_count + 1 && ac_count=$as_val
if test $ac_count -gt ${ac_path_EGREP_max-0}; then
# Best one so far, save it but keep looking for a better one
ac_cv_path_EGREP="$ac_path_EGREP"
ac_path_EGREP_max=$ac_count
fi
# 10*(2^10) chars as input seems more than enough
test $ac_count -gt 10 && break
done
rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
esac
$ac_path_EGREP_found && break 3
done
done
done
IFS=$as_save_IFS
if test -z "$ac_cv_path_EGREP"; then
as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
fi
else
ac_cv_path_EGREP=$EGREP
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
$as_echo "$ac_cv_path_EGREP" >&6; }
EGREP="$ac_cv_path_EGREP"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
if test -z "$MKDIR_P"; then
if ${ac_cv_path_mkdir+:} false; then :
$as_echo_n "(cached) " >&6
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_prog in mkdir gmkdir; do
for ac_exec_ext in '' $ac_executable_extensions; do
as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
'mkdir (GNU coreutils) '* | \
'mkdir (coreutils) '* | \
'mkdir (fileutils) '4.1*)
ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
break 3;;
esac
done
done
done
IFS=$as_save_IFS
fi
test -d ./--version && rmdir ./--version
if test "${ac_cv_path_mkdir+set}" = set; then
MKDIR_P="$ac_cv_path_mkdir -p"
else
# As a last resort, use the slow shell script. Don't cache a
# value for MKDIR_P within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
MKDIR_P="$ac_install_sh -d"
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
$as_echo "$MKDIR_P" >&6; }
if test -n "$ac_tool_prefix"; then
for ac_prog in ar
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_AR+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$AR" && break
done
fi
if test -z "$AR"; then
ac_ct_AR=$AR
for ac_prog in ar
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_ac_ct_AR+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_AR="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
$as_echo "$ac_ct_AR" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$ac_ct_AR" && break
done
if test "x$ac_ct_AR" = x; then
AR=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
fi
fi
# Extract the first word of "cat", so it can be a program name with args.
set dummy cat; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_CAT+:} false; then :
$as_echo_n "(cached) " >&6
else
case $CAT in
[\\/]* | ?:[\\/]*)
ac_cv_path_CAT="$CAT" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_CAT="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
CAT=$ac_cv_path_CAT
if test -n "$CAT"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAT" >&5
$as_echo "$CAT" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "kill", so it can be a program name with args.
set dummy kill; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_KILL+:} false; then :
$as_echo_n "(cached) " >&6
else
case $KILL in
[\\/]* | ?:[\\/]*)
ac_cv_path_KILL="$KILL" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_KILL="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
KILL=$ac_cv_path_KILL
if test -n "$KILL"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $KILL" >&5
$as_echo "$KILL" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "sed", so it can be a program name with args.
set dummy sed; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_SED+:} false; then :
$as_echo_n "(cached) " >&6
else
case $SED in
[\\/]* | ?:[\\/]*)
ac_cv_path_SED="$SED" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_SED="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
SED=$ac_cv_path_SED
if test -n "$SED"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5
$as_echo "$SED" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "ent", so it can be a program name with args.
set dummy ent; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_ENT+:} false; then :
$as_echo_n "(cached) " >&6
else
case $ENT in
[\\/]* | ?:[\\/]*)
ac_cv_path_ENT="$ENT" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_ENT="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
ENT=$ac_cv_path_ENT
if test -n "$ENT"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENT" >&5
$as_echo "$ENT" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "bash", so it can be a program name with args.
set dummy bash; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_TEST_MINUS_S_SH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $TEST_MINUS_S_SH in
[\\/]* | ?:[\\/]*)
ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
if test -n "$TEST_MINUS_S_SH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5
$as_echo "$TEST_MINUS_S_SH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "ksh", so it can be a program name with args.
set dummy ksh; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_TEST_MINUS_S_SH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $TEST_MINUS_S_SH in
[\\/]* | ?:[\\/]*)
ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
if test -n "$TEST_MINUS_S_SH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5
$as_echo "$TEST_MINUS_S_SH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "sh", so it can be a program name with args.
set dummy sh; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_TEST_MINUS_S_SH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $TEST_MINUS_S_SH in
[\\/]* | ?:[\\/]*)
ac_cv_path_TEST_MINUS_S_SH="$TEST_MINUS_S_SH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_TEST_MINUS_S_SH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
TEST_MINUS_S_SH=$ac_cv_path_TEST_MINUS_S_SH
if test -n "$TEST_MINUS_S_SH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEST_MINUS_S_SH" >&5
$as_echo "$TEST_MINUS_S_SH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "sh", so it can be a program name with args.
set dummy sh; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_SH+:} false; then :
$as_echo_n "(cached) " >&6
else
case $SH in
[\\/]* | ?:[\\/]*)
ac_cv_path_SH="$SH" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_SH="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
SH=$ac_cv_path_SH
if test -n "$SH"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $SH" >&5
$as_echo "$SH" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "groff", so it can be a program name with args.
set dummy groff; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_GROFF+:} false; then :
$as_echo_n "(cached) " >&6
else
case $GROFF in
[\\/]* | ?:[\\/]*)
ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_GROFF="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
GROFF=$ac_cv_path_GROFF
if test -n "$GROFF"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5
$as_echo "$GROFF" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "nroff", so it can be a program name with args.
set dummy nroff; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_NROFF+:} false; then :
$as_echo_n "(cached) " >&6
else
case $NROFF in
[\\/]* | ?:[\\/]*)
ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
NROFF=$ac_cv_path_NROFF
if test -n "$NROFF"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5
$as_echo "$NROFF" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "mandoc", so it can be a program name with args.
set dummy mandoc; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_MANDOC+:} false; then :
$as_echo_n "(cached) " >&6
else
case $MANDOC in
[\\/]* | ?:[\\/]*)
ac_cv_path_MANDOC="$MANDOC" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_MANDOC="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
MANDOC=$ac_cv_path_MANDOC
if test -n "$MANDOC"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANDOC" >&5
$as_echo "$MANDOC" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
TEST_SHELL=sh
if test "x$MANDOC" != "x" ; then
MANFMT="$MANDOC"
elif test "x$NROFF" != "x" ; then
MANFMT="$NROFF -mandoc"
elif test "x$GROFF" != "x" ; then
MANFMT="$GROFF -mandoc -Tascii"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no manpage formatted found" >&5
$as_echo "$as_me: WARNING: no manpage formatted found" >&2;}
MANFMT="false"
fi
# Extract the first word of "groupadd", so it can be a program name with args.
set dummy groupadd; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PATH_GROUPADD_PROG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PATH_GROUPADD_PROG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATH_GROUPADD_PROG="$PATH_GROUPADD_PROG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /usr/sbin${PATH_SEPARATOR}/etc
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PATH_GROUPADD_PROG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_PATH_GROUPADD_PROG" && ac_cv_path_PATH_GROUPADD_PROG="groupadd"
;;
esac
fi
PATH_GROUPADD_PROG=$ac_cv_path_PATH_GROUPADD_PROG
if test -n "$PATH_GROUPADD_PROG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_GROUPADD_PROG" >&5
$as_echo "$PATH_GROUPADD_PROG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "useradd", so it can be a program name with args.
set dummy useradd; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PATH_USERADD_PROG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PATH_USERADD_PROG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATH_USERADD_PROG="$PATH_USERADD_PROG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in /usr/sbin${PATH_SEPARATOR}/etc
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PATH_USERADD_PROG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_PATH_USERADD_PROG" && ac_cv_path_PATH_USERADD_PROG="useradd"
;;
esac
fi
PATH_USERADD_PROG=$ac_cv_path_PATH_USERADD_PROG
if test -n "$PATH_USERADD_PROG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_USERADD_PROG" >&5
$as_echo "$PATH_USERADD_PROG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "pkgmk", so it can be a program name with args.
set dummy pkgmk; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_MAKE_PACKAGE_SUPPORTED+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$MAKE_PACKAGE_SUPPORTED"; then
ac_cv_prog_MAKE_PACKAGE_SUPPORTED="$MAKE_PACKAGE_SUPPORTED" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_MAKE_PACKAGE_SUPPORTED="yes"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_prog_MAKE_PACKAGE_SUPPORTED" && ac_cv_prog_MAKE_PACKAGE_SUPPORTED="no"
fi
fi
MAKE_PACKAGE_SUPPORTED=$ac_cv_prog_MAKE_PACKAGE_SUPPORTED
if test -n "$MAKE_PACKAGE_SUPPORTED"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKE_PACKAGE_SUPPORTED" >&5
$as_echo "$MAKE_PACKAGE_SUPPORTED" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test -x /sbin/sh; then
STARTUP_SCRIPT_SHELL=/sbin/sh
else
STARTUP_SCRIPT_SHELL=/bin/sh
fi
# System features
# Check whether --enable-largefile was given.
if test "${enable_largefile+set}" = set; then :
enableval=$enable_largefile;
fi
if test "$enable_largefile" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
if ${ac_cv_sys_largefile_CC+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_sys_largefile_CC=no
if test "$GCC" != yes; then
ac_save_CC=$CC
while :; do
# IRIX 6.2 and later do not support large files by default,
# so use the C compiler's -n32 option if that helps.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
break
fi
rm -f core conftest.err conftest.$ac_objext
CC="$CC -n32"
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_largefile_CC=' -n32'; break
fi
rm -f core conftest.err conftest.$ac_objext
break
done
CC=$ac_save_CC
rm -f conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
$as_echo "$ac_cv_sys_largefile_CC" >&6; }
if test "$ac_cv_sys_largefile_CC" != no; then
CC=$CC$ac_cv_sys_largefile_CC
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
if ${ac_cv_sys_file_offset_bits+:} false; then :
$as_echo_n "(cached) " >&6
else
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _FILE_OFFSET_BITS 64
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_file_offset_bits=64; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_sys_file_offset_bits=unknown
break
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
case $ac_cv_sys_file_offset_bits in #(
no | unknown) ;;
*)
cat >>confdefs.h <<_ACEOF
#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
_ACEOF
;;
esac
rm -rf conftest*
if test $ac_cv_sys_file_offset_bits = unknown; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
if ${ac_cv_sys_large_files+:} false; then :
$as_echo_n "(cached) " >&6
else
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=no; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _LARGE_FILES 1
#include <sys/types.h>
/* Check that off_t can represent 2**63 - 1 correctly.
We can't simply define LARGE_OFF_T to be 9223372036854775807,
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_sys_large_files=1; break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_sys_large_files=unknown
break
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
$as_echo "$ac_cv_sys_large_files" >&6; }
case $ac_cv_sys_large_files in #(
no | unknown) ;;
*)
cat >>confdefs.h <<_ACEOF
#define _LARGE_FILES $ac_cv_sys_large_files
_ACEOF
;;
esac
rm -rf conftest*
fi
fi
if test -z "$AR" ; then
as_fn_error $? "*** 'ar' missing, please install or fix your \$PATH ***" "$LINENO" 5
fi
# Extract the first word of "passwd", so it can be a program name with args.
set dummy passwd; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PATH_PASSWD_PROG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PATH_PASSWD_PROG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PATH_PASSWD_PROG="$PATH_PASSWD_PROG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PATH_PASSWD_PROG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PATH_PASSWD_PROG=$ac_cv_path_PATH_PASSWD_PROG
if test -n "$PATH_PASSWD_PROG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_PASSWD_PROG" >&5
$as_echo "$PATH_PASSWD_PROG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test ! -z "$PATH_PASSWD_PROG" ; then
cat >>confdefs.h <<_ACEOF
#define _PATH_PASSWD_PROG "$PATH_PASSWD_PROG"
_ACEOF
fi
LD="$CC"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
if ${ac_cv_c_inline+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef __cplusplus
typedef int foo_t;
static $ac_kw foo_t static_foo () {return 0; }
$ac_kw foo_t foo () {return 0; }
#endif
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_c_inline=$ac_kw
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
test "$ac_cv_c_inline" != no && break
done
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
$as_echo "$ac_cv_c_inline" >&6; }
case $ac_cv_c_inline in
inline | yes) ;;
*)
case $ac_cv_c_inline in
no) ac_val=;;
*) ac_val=$ac_cv_c_inline;;
esac
cat >>confdefs.h <<_ACEOF
#ifndef __cplusplus
#define inline $ac_val
#endif
_ACEOF
;;
esac
ac_fn_c_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include <limits.h>
"
if test "x$ac_cv_have_decl_LLONG_MAX" = xyes; then :
have_llong_max=1
fi
ac_fn_c_check_decl "$LINENO" "SYSTR_POLICY_KILL" "ac_cv_have_decl_SYSTR_POLICY_KILL" "
#include <sys/types.h>
#include <sys/param.h>
#include <dev/systrace.h>
"
if test "x$ac_cv_have_decl_SYSTR_POLICY_KILL" = xyes; then :
have_systr_policy_kill=1
fi
ac_fn_c_check_decl "$LINENO" "RLIMIT_NPROC" "ac_cv_have_decl_RLIMIT_NPROC" "
#include <sys/types.h>
#include <sys/resource.h>
"
if test "x$ac_cv_have_decl_RLIMIT_NPROC" = xyes; then :
$as_echo "#define HAVE_RLIMIT_NPROC /**/" >>confdefs.h
fi
ac_fn_c_check_decl "$LINENO" "PR_SET_NO_NEW_PRIVS" "ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" "
#include <sys/types.h>
#include <linux/prctl.h>
"
if test "x$ac_cv_have_decl_PR_SET_NO_NEW_PRIVS" = xyes; then :
have_linux_no_new_privs=1
fi
openssl=yes
# Check whether --with-openssl was given.
if test "${with_openssl+set}" = set; then :
withval=$with_openssl; if test "x$withval" = "xno" ; then
openssl=no
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL will be used for cryptography" >&5
$as_echo_n "checking whether OpenSSL will be used for cryptography... " >&6; }
if test "x$openssl" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
cat >>confdefs.h <<_ACEOF
#define WITH_OPENSSL 1
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
use_stack_protector=1
use_toolchain_hardening=1
# Check whether --with-stackprotect was given.
if test "${with_stackprotect+set}" = set; then :
withval=$with_stackprotect;
if test "x$withval" = "xno"; then
use_stack_protector=0
fi
fi
# Check whether --with-hardening was given.
if test "${with_hardening+set}" = set; then :
withval=$with_hardening;
if test "x$withval" = "xno"; then
use_toolchain_hardening=0
fi
fi
# We use -Werror for the tests only so that we catch warnings like "this is
# on by default" for things like -fPIE.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports -Werror" >&5
$as_echo_n "checking if $CC supports -Werror... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
WERROR="-Werror"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
WERROR=""
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CFLAGS="$saved_CFLAGS"
if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5
$as_echo_n "checking if $CC supports compile flag -pipe... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -pipe"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-pipe"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5
$as_echo_n "checking if $CC supports compile flag -Qunused-arguments... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Qunused-arguments"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Qunused-arguments"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunknown-warning-option" >&5
$as_echo_n "checking if $CC supports compile flag -Wunknown-warning-option... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wunknown-warning-option"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wunknown-warning-option"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wall" >&5
$as_echo_n "checking if $CC supports compile flag -Wall... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wall"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wall"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-arith" >&5
$as_echo_n "checking if $CC supports compile flag -Wpointer-arith... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wpointer-arith"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wpointer-arith"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wuninitialized" >&5
$as_echo_n "checking if $CC supports compile flag -Wuninitialized... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wuninitialized"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wuninitialized"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsign-compare" >&5
$as_echo_n "checking if $CC supports compile flag -Wsign-compare... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wsign-compare"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wsign-compare"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wformat-security" >&5
$as_echo_n "checking if $CC supports compile flag -Wformat-security... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wformat-security"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wformat-security"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5
$as_echo_n "checking if $CC supports compile flag -Wsizeof-pointer-memaccess... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wsizeof-pointer-memaccess"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wsizeof-pointer-memaccess"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-sign" >&5
$as_echo_n "checking if $CC supports compile flag -Wpointer-sign... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wpointer-sign"
_define_flag="-Wno-pointer-sign"
test "x$_define_flag" = "x" && _define_flag="-Wpointer-sign"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-result" >&5
$as_echo_n "checking if $CC supports compile flag -Wunused-result... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wunused-result"
_define_flag="-Wno-unused-result"
test "x$_define_flag" = "x" && _define_flag="-Wunused-result"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fno-strict-aliasing" >&5
$as_echo_n "checking if $CC supports compile flag -fno-strict-aliasing... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -fno-strict-aliasing"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-fno-strict-aliasing"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
if test "x$use_toolchain_hardening" = "x1"; then
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -mretpoline" >&5
$as_echo_n "checking if $CC supports compile flag -mretpoline... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -mretpoline"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-mretpoline"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
} # clang
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,retpolineplt" >&5
$as_echo_n "checking if $LD supports link flag -Wl,-z,retpolineplt... " >&6; }
saved_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $WERROR -Wl,-z,retpolineplt"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wl,-z,retpolineplt"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
long long p = n * o;
printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
LDFLAGS="$saved_LDFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5
$as_echo_n "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -D_FORTIFY_SOURCE=2"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-D_FORTIFY_SOURCE=2"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5
$as_echo_n "checking if $LD supports link flag -Wl,-z,relro... " >&6; }
saved_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $WERROR -Wl,-z,relro"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wl,-z,relro"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
long long p = n * o;
printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
LDFLAGS="$saved_LDFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,now" >&5
$as_echo_n "checking if $LD supports link flag -Wl,-z,now... " >&6; }
saved_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $WERROR -Wl,-z,now"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wl,-z,now"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
long long p = n * o;
printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
LDFLAGS="$saved_LDFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,noexecstack" >&5
$as_echo_n "checking if $LD supports link flag -Wl,-z,noexecstack... " >&6; }
saved_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $WERROR -Wl,-z,noexecstack"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wl,-z,noexecstack"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
long long p = n * o;
printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
LDFLAGS="$saved_LDFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
}
# NB. -ftrapv expects certain support functions to be present in
# the compiler library (libgcc or similar) to detect integer operations
# that can overflow. We must check that the result of enabling it
# actually links. The test program compiled/linked includes a number
# of integer operations that should exercise this.
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrapv and linking succeeds" >&5
$as_echo_n "checking if $CC supports compile flag -ftrapv and linking succeeds... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -ftrapv"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-ftrapv"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
long long int p = n * o;
printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
}
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gcc version" >&5
$as_echo_n "checking gcc version... " >&6; }
GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'`
case $GCC_VER in
1.*) no_attrib_nonnull=1 ;;
2.8* | 2.9*)
no_attrib_nonnull=1
;;
2.*) no_attrib_nonnull=1 ;;
*) ;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $GCC_VER" >&5
$as_echo "$GCC_VER" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -fno-builtin-memset" >&5
$as_echo_n "checking if $CC accepts -fno-builtin-memset... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fno-builtin-memset"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
int
main ()
{
char b[10]; memset(b, 0, sizeof(b));
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
# -fstack-protector-all doesn't always work for some GCC versions
# and/or platforms, so we test if we can. If it's not supported
# on a given platform gcc will emit a warning so we use -Werror.
if test "x$use_stack_protector" = "x1"; then
for t in -fstack-protector-strong -fstack-protector-all \
-fstack-protector; do
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports $t" >&5
$as_echo_n "checking if $CC supports $t... " >&6; }
saved_CFLAGS="$CFLAGS"
saved_LDFLAGS="$LDFLAGS"
CFLAGS="$CFLAGS $t -Werror"
LDFLAGS="$LDFLAGS $t -Werror"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
char x[256];
snprintf(x, sizeof(x), "XXX");
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $t"
LDFLAGS="$saved_LDFLAGS $t"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $t works" >&5
$as_echo_n "checking if $t works... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: cannot test" >&5
$as_echo "$as_me: WARNING: cross compiling: cannot test" >&2;}
break
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
char x[256];
snprintf(x, sizeof(x), "XXX");
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
break
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
CFLAGS="$saved_CFLAGS"
LDFLAGS="$saved_LDFLAGS"
done
fi
if test -z "$have_llong_max"; then
# retry LLONG_MAX with -std=gnu99, needed on some Linuxes
unset ac_cv_have_decl_LLONG_MAX
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -std=gnu99"
ac_fn_c_check_decl "$LINENO" "LLONG_MAX" "ac_cv_have_decl_LLONG_MAX" "#include <limits.h>
"
if test "x$ac_cv_have_decl_LLONG_MAX" = xyes; then :
have_llong_max=1
else
CFLAGS="$saved_CFLAGS"
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ on return types" >&5
$as_echo_n "checking if compiler allows __attribute__ on return types... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
__attribute__((__unused__)) static void foo(void){return;}
int
main ()
{
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define NO_ATTRIBUTE_ON_RETURN_TYPE 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__ prototype args" >&5
$as_echo_n "checking if compiler allows __attribute__ prototype args... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));
int
main ()
{
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define NO_ATTRIBUTE_ON_PROTOTYPE_ARGS 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "x$no_attrib_nonnull" != "x1" ; then
$as_echo "#define HAVE_ATTRIBUTE__NONNULL__ 1" >>confdefs.h
fi
# Check whether --with-rpath was given.
if test "${with_rpath+set}" = set; then :
withval=$with_rpath;
if test "x$withval" = "xno" ; then
- need_dash_r=""
- fi
- if test "x$withval" = "xyes" ; then
- need_dash_r=1
+ rpath_opt=""
+ elif test "x$withval" = "xyes" ; then
+ rpath_opt="-R"
+ else
+ rpath_opt="$withval"
fi
fi
# Allow user to specify flags
# Check whether --with-cflags was given.
if test "${with_cflags+set}" = set; then :
withval=$with_cflags;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CFLAGS="$CFLAGS $withval"
fi
fi
# Check whether --with-cflags-after was given.
if test "${with_cflags_after+set}" = set; then :
withval=$with_cflags_after;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CFLAGS_AFTER="$withval"
fi
fi
# Check whether --with-cppflags was given.
if test "${with_cppflags+set}" = set; then :
withval=$with_cppflags;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CPPFLAGS="$CPPFLAGS $withval"
fi
fi
# Check whether --with-ldflags was given.
if test "${with_ldflags+set}" = set; then :
withval=$with_ldflags;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LDFLAGS="$LDFLAGS $withval"
fi
fi
# Check whether --with-ldflags-after was given.
if test "${with_ldflags_after+set}" = set; then :
withval=$with_ldflags_after;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LDFLAGS_AFTER="$withval"
fi
fi
# Check whether --with-libs was given.
if test "${with_libs+set}" = set; then :
withval=$with_libs;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LIBS="$LIBS $withval"
fi
fi
# Check whether --with-Werror was given.
if test "${with_Werror+set}" = set; then :
withval=$with_Werror;
if test -n "$withval" && test "x$withval" != "xno"; then
werror_flags="-Werror"
if test "x${withval}" != "xyes"; then
werror_flags="$withval"
fi
fi
fi
for ac_header in \
blf.h \
bstring.h \
crypt.h \
crypto/sha2.h \
dirent.h \
endian.h \
elf.h \
err.h \
features.h \
fcntl.h \
floatingpoint.h \
getopt.h \
glob.h \
ia.h \
iaf.h \
ifaddrs.h \
inttypes.h \
langinfo.h \
limits.h \
locale.h \
login.h \
maillock.h \
ndir.h \
net/if_tun.h \
netdb.h \
netgroup.h \
pam/pam_appl.h \
paths.h \
poll.h \
pty.h \
readpassphrase.h \
rpc/types.h \
security/pam_appl.h \
sha2.h \
shadow.h \
stddef.h \
stdint.h \
string.h \
strings.h \
sys/bitypes.h \
sys/bsdtty.h \
sys/cdefs.h \
sys/dir.h \
sys/file.h \
sys/mman.h \
sys/label.h \
sys/ndir.h \
sys/poll.h \
sys/prctl.h \
sys/pstat.h \
sys/ptrace.h \
sys/random.h \
sys/select.h \
sys/stat.h \
sys/stream.h \
sys/stropts.h \
sys/strtio.h \
sys/statvfs.h \
sys/sysmacros.h \
sys/time.h \
sys/timers.h \
sys/vfs.h \
time.h \
tmpdir.h \
ttyent.h \
ucred.h \
unistd.h \
usersec.h \
util.h \
utime.h \
utmp.h \
utmpx.h \
vis.h \
wchar.h \
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
# On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h]
# to be included first.
for ac_header in sys/audit.h
do :
ac_fn_c_check_header_compile "$LINENO" "sys/audit.h" "ac_cv_header_sys_audit_h" "
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_LABEL_H
# include <sys/label.h>
#endif
"
if test "x$ac_cv_header_sys_audit_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_AUDIT_H 1
_ACEOF
fi
done
# sys/capsicum.h requires sys/types.h
for ac_header in sys/capsicum.h
do :
ac_fn_c_check_header_compile "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" "
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
"
if test "x$ac_cv_header_sys_capsicum_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_CAPSICUM_H 1
_ACEOF
fi
done
# net/route.h requires sys/socket.h and sys/types.h.
# sys/sysctl.h also requires sys/param.h
for ac_header in net/route.h sys/sysctl.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/socket.h>
"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
# lastlog.h requires sys/time.h to be included first on Solaris
for ac_header in lastlog.h
do :
ac_fn_c_check_header_compile "$LINENO" "lastlog.h" "ac_cv_header_lastlog_h" "
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
"
if test "x$ac_cv_header_lastlog_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LASTLOG_H 1
_ACEOF
fi
done
# sys/ptms.h requires sys/stream.h to be included first on Solaris
for ac_header in sys/ptms.h
do :
ac_fn_c_check_header_compile "$LINENO" "sys/ptms.h" "ac_cv_header_sys_ptms_h" "
#ifdef HAVE_SYS_STREAM_H
# include <sys/stream.h>
#endif
"
if test "x$ac_cv_header_sys_ptms_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_PTMS_H 1
_ACEOF
fi
done
# login_cap.h requires sys/types.h on NetBSD
for ac_header in login_cap.h
do :
ac_fn_c_check_header_compile "$LINENO" "login_cap.h" "ac_cv_header_login_cap_h" "
#include <sys/types.h>
"
if test "x$ac_cv_header_login_cap_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LOGIN_CAP_H 1
_ACEOF
fi
done
# older BSDs need sys/param.h before sys/mount.h
for ac_header in sys/mount.h
do :
ac_fn_c_check_header_compile "$LINENO" "sys/mount.h" "ac_cv_header_sys_mount_h" "
#include <sys/param.h>
"
if test "x$ac_cv_header_sys_mount_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_MOUNT_H 1
_ACEOF
fi
done
# Android requires sys/socket.h to be included before sys/un.h
for ac_header in sys/un.h
do :
ac_fn_c_check_header_compile "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" "
#include <sys/types.h>
#include <sys/socket.h>
"
if test "x$ac_cv_header_sys_un_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_UN_H 1
_ACEOF
fi
done
# Messages for features tested for in target-specific section
SIA_MSG="no"
SPC_MSG="no"
SP_MSG="no"
SPP_MSG="no"
# Support for Solaris/Illumos privileges (this test is used by both
# the --with-solaris-privs option and --with-sandbox=solaris).
SOLARIS_PRIVS="no"
# Check for some target-specific stuff
case "$host" in
*-*-aix*)
# Some versions of VAC won't allow macro redefinitions at
# -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that
# particularly with older versions of vac or xlc.
# It also throws errors about null macro arguments, but these are
# not fatal.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows macro redefinitions" >&5
$as_echo_n "checking if compiler allows macro redefinitions... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define testmacro foo
#define testmacro bar
int
main ()
{
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`"
CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`"
CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to specify blibpath for linker ($LD)" >&5
$as_echo_n "checking how to specify blibpath for linker ($LD)... " >&6; }
if (test -z "$blibpath"); then
blibpath="/usr/lib:/lib"
fi
saved_LDFLAGS="$LDFLAGS"
if test "$GCC" = "yes"; then
flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:"
else
flags="-blibpath: -Wl,-blibpath: -Wl,-rpath,"
fi
for tryflags in $flags ;do
if (test -z "$blibflags"); then
LDFLAGS="$saved_LDFLAGS $tryflags$blibpath"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
blibflags=$tryflags
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
done
if (test -z "$blibflags"); then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
as_fn_error $? "*** must be able to specify blibpath on AIX - check config.log" "$LINENO" 5
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $blibflags" >&5
$as_echo "$blibflags" >&6; }
fi
LDFLAGS="$saved_LDFLAGS"
ac_fn_c_check_func "$LINENO" "authenticate" "ac_cv_func_authenticate"
if test "x$ac_cv_func_authenticate" = xyes; then :
$as_echo "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for authenticate in -ls" >&5
$as_echo_n "checking for authenticate in -ls... " >&6; }
if ${ac_cv_lib_s_authenticate+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ls $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char authenticate ();
int
main ()
{
return authenticate ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_s_authenticate=yes
else
ac_cv_lib_s_authenticate=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_s_authenticate" >&5
$as_echo "$ac_cv_lib_s_authenticate" >&6; }
if test "x$ac_cv_lib_s_authenticate" = xyes; then :
$as_echo "#define WITH_AIXAUTHENTICATE 1" >>confdefs.h
LIBS="$LIBS -ls"
fi
fi
ac_fn_c_check_decl "$LINENO" "authenticate" "ac_cv_have_decl_authenticate" "#include <usersec.h>
"
if test "x$ac_cv_have_decl_authenticate" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_AUTHENTICATE $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "loginrestrictions" "ac_cv_have_decl_loginrestrictions" "#include <usersec.h>
"
if test "x$ac_cv_have_decl_loginrestrictions" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_LOGINRESTRICTIONS $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "loginsuccess" "ac_cv_have_decl_loginsuccess" "#include <usersec.h>
"
if test "x$ac_cv_have_decl_loginsuccess" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_LOGINSUCCESS $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "passwdexpired" "ac_cv_have_decl_passwdexpired" "#include <usersec.h>
"
if test "x$ac_cv_have_decl_passwdexpired" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_PASSWDEXPIRED $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "setauthdb" "ac_cv_have_decl_setauthdb" "#include <usersec.h>
"
if test "x$ac_cv_have_decl_setauthdb" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_SETAUTHDB $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "loginfailed" "ac_cv_have_decl_loginfailed" "#include <usersec.h>
"
if test "x$ac_cv_have_decl_loginfailed" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_LOGINFAILED $ac_have_decl
_ACEOF
if test $ac_have_decl = 1; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if loginfailed takes 4 arguments" >&5
$as_echo_n "checking if loginfailed takes 4 arguments... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <usersec.h>
int
main ()
{
(void)loginfailed("user","host","tty",0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define AIX_LOGINFAILED_4ARG 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
for ac_func in getgrset setauthdb
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
ac_fn_c_check_decl "$LINENO" "F_CLOSEM" "ac_cv_have_decl_F_CLOSEM" " #include <limits.h>
#include <fcntl.h>
"
if test "x$ac_cv_have_decl_F_CLOSEM" = xyes; then :
$as_echo "#define HAVE_FCNTL_CLOSEM 1" >>confdefs.h
fi
check_for_aix_broken_getaddrinfo=1
$as_echo "#define BROKEN_REALPATH 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
$as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h
$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
$as_echo "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h
$as_echo "#define PTY_ZEROREAD 1" >>confdefs.h
$as_echo "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h
$as_echo "#define BROKEN_STRNDUP 1" >>confdefs.h
$as_echo "#define BROKEN_STRNLEN 1" >>confdefs.h
;;
*-*-android*)
$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
$as_echo "#define DISABLE_WTMP 1" >>confdefs.h
;;
*-*-cygwin*)
check_for_libcrypt_later=1
LIBS="$LIBS /usr/lib/textreadmode.o"
$as_echo "#define HAVE_CYGWIN 1" >>confdefs.h
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h
$as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
$as_echo "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h
$as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
$as_echo "#define SSH_IOBUFSZ 65535" >>confdefs.h
$as_echo "#define FILESYSTEM_NO_BACKSLASH 1" >>confdefs.h
# Cygwin defines optargs, optargs as declspec(dllimport) for historical
# reasons which cause compile warnings, so we disable those warnings.
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-attributes" >&5
$as_echo_n "checking if $CC supports compile flag -Wno-attributes... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -Wno-attributes"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-Wno-attributes"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
;;
*-*-dgux*)
$as_echo "#define IP_TOS_IS_BROKEN 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
;;
*-*-darwin*)
use_pie=auto
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we have working getaddrinfo" >&5
$as_echo_n "checking if we have working getaddrinfo... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: assume it is working" >&5
$as_echo "assume it is working" >&6; }
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <mach-o/dyld.h>
main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
exit(0);
else
exit(1);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: working" >&5
$as_echo "working" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: buggy" >&5
$as_echo "buggy" >&6; }
$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define BROKEN_GLOB 1" >>confdefs.h
cat >>confdefs.h <<_ACEOF
#define BIND_8_COMPAT 1
_ACEOF
$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h
$as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h
$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default"
if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then :
else
$as_echo "#define AU_IPv4 0" >>confdefs.h
#include <bsm/audit.h>
$as_echo "#define LASTLOG_WRITE_PUTUTXLINE 1" >>confdefs.h
fi
$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
for ac_func in sandbox_init
do :
ac_fn_c_check_func "$LINENO" "sandbox_init" "ac_cv_func_sandbox_init"
if test "x$ac_cv_func_sandbox_init" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SANDBOX_INIT 1
_ACEOF
fi
done
for ac_header in sandbox.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "sandbox.h" "ac_cv_header_sandbox_h" "$ac_includes_default"
if test "x$ac_cv_header_sandbox_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SANDBOX_H 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sandbox_apply in -lsandbox" >&5
$as_echo_n "checking for sandbox_apply in -lsandbox... " >&6; }
if ${ac_cv_lib_sandbox_sandbox_apply+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsandbox $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char sandbox_apply ();
int
main ()
{
return sandbox_apply ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_sandbox_sandbox_apply=yes
else
ac_cv_lib_sandbox_sandbox_apply=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sandbox_sandbox_apply" >&5
$as_echo "$ac_cv_lib_sandbox_sandbox_apply" >&6; }
if test "x$ac_cv_lib_sandbox_sandbox_apply" = xyes; then :
SSHDLIBS="$SSHDLIBS -lsandbox"
fi
;;
*-*-dragonfly*)
SSHDLIBS="$SSHDLIBS -lcrypt"
TEST_MALLOC_OPTIONS="AFGJPRX"
;;
*-*-haiku*)
LIBS="$LIBS -lbsd "
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lnetwork" >&5
$as_echo_n "checking for socket in -lnetwork... " >&6; }
if ${ac_cv_lib_network_socket+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lnetwork $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char socket ();
int
main ()
{
return socket ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_network_socket=yes
else
ac_cv_lib_network_socket=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_socket" >&5
$as_echo "$ac_cv_lib_network_socket" >&6; }
if test "x$ac_cv_lib_network_socket" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBNETWORK 1
_ACEOF
LIBS="-lnetwork $LIBS"
fi
$as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h
MANTYPE=man
;;
*-*-hpux*)
# first we define all of the options common to all HP-UX releases
CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
IPADDR_IN_DISPLAY=yes
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_STRING \"*\"" >>confdefs.h
$as_echo "#define SPT_TYPE SPT_PSTAT" >>confdefs.h
$as_echo "#define PLATFORM_SYS_DIR_UID 2" >>confdefs.h
maildir="/var/mail"
LIBS="$LIBS -lsec"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for t_error in -lxnet" >&5
$as_echo_n "checking for t_error in -lxnet... " >&6; }
if ${ac_cv_lib_xnet_t_error+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lxnet $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char t_error ();
int
main ()
{
return t_error ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_xnet_t_error=yes
else
ac_cv_lib_xnet_t_error=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_t_error" >&5
$as_echo "$ac_cv_lib_xnet_t_error" >&6; }
if test "x$ac_cv_lib_xnet_t_error" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBXNET 1
_ACEOF
LIBS="-lxnet $LIBS"
else
as_fn_error $? "*** -lxnet needed on HP-UX - check config.log ***" "$LINENO" 5
fi
# next, we define all of the options specific to major releases
case "$host" in
*-*-hpux10*)
if test -z "$GCC"; then
CFLAGS="$CFLAGS -Ae"
fi
;;
*-*-hpux11*)
$as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
$as_echo "#define USE_BTMP 1" >>confdefs.h
check_for_hpux_broken_getaddrinfo=1
check_for_conflicting_getspnam=1
;;
esac
# lastly, we define options specific to minor releases
case "$host" in
*-*-hpux10.26)
$as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h
disable_ptmx_check=yes
LIBS="$LIBS -lsecpw"
;;
esac
;;
*-*-irix5*)
PATH="$PATH:/usr/etc"
$as_echo "#define BROKEN_INET_NTOA 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
;;
*-*-irix6*)
PATH="$PATH:/usr/etc"
$as_echo "#define WITH_IRIX_ARRAY 1" >>confdefs.h
$as_echo "#define WITH_IRIX_PROJECT 1" >>confdefs.h
$as_echo "#define WITH_IRIX_AUDIT 1" >>confdefs.h
ac_fn_c_check_func "$LINENO" "jlimit_startjob" "ac_cv_func_jlimit_startjob"
if test "x$ac_cv_func_jlimit_startjob" = xyes; then :
$as_echo "#define WITH_IRIX_JOBS 1" >>confdefs.h
fi
$as_echo "#define BROKEN_INET_NTOA 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h
$as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
;;
*-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
check_for_libcrypt_later=1
$as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h
$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
$as_echo "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h
$as_echo "#define USE_BTMP 1" >>confdefs.h
;;
*-*-linux*)
no_dev_ptmx=1
use_pie=auto
check_for_libcrypt_later=1
check_for_openpty_ctty_bug=1
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE"
$as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_PREFIX \"!\"" >>confdefs.h
$as_echo "#define SPT_TYPE SPT_REUSEARGV" >>confdefs.h
$as_echo "#define LINK_OPNOTSUPP_ERRNO EPERM" >>confdefs.h
$as_echo "#define _PATH_BTMP \"/var/log/btmp\"" >>confdefs.h
$as_echo "#define USE_BTMP 1" >>confdefs.h
$as_echo "#define LINUX_OOM_ADJUST 1" >>confdefs.h
inet6_default_4in6=yes
case `uname -r` in
1.*|2.0.*)
$as_echo "#define BROKEN_CMSG_TYPE 1" >>confdefs.h
;;
esac
# tun(4) forwarding compat code
for ac_header in linux/if_tun.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" "$ac_includes_default"
if test "x$ac_cv_header_linux_if_tun_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LINUX_IF_TUN_H 1
_ACEOF
fi
done
if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then
$as_echo "#define SSH_TUN_LINUX 1" >>confdefs.h
$as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h
$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
fi
ac_fn_c_check_header_compile "$LINENO" "linux/if.h" "ac_cv_header_linux_if_h" "
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.H>
#endif
"
if test "x$ac_cv_header_linux_if_h" = xyes; then :
$as_echo "#define SYS_RDOMAIN_LINUX 1" >>confdefs.h
fi
for ac_header in linux/seccomp.h linux/filter.h linux/audit.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#include <linux/types.h>
"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
# Obtain MIPS ABI
case "$host" in
mips*)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if _MIPS_SIM != _ABIO32
#error
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
mips_abi="o32"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if _MIPS_SIM != _ABIN32
#error
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
mips_abi="n32"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if _MIPS_SIM != _ABI64
#error
#endif
int
main ()
{
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
mips_abi="n64"
else
as_fn_error $? "unknown MIPS ABI" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for seccomp architecture" >&5
$as_echo_n "checking for seccomp architecture... " >&6; }
seccomp_audit_arch=
case "$host" in
x86_64-*)
seccomp_audit_arch=AUDIT_ARCH_X86_64
;;
i*86-*)
seccomp_audit_arch=AUDIT_ARCH_I386
;;
arm*-*)
seccomp_audit_arch=AUDIT_ARCH_ARM
;;
aarch64*-*)
seccomp_audit_arch=AUDIT_ARCH_AARCH64
;;
s390x-*)
seccomp_audit_arch=AUDIT_ARCH_S390X
;;
s390-*)
seccomp_audit_arch=AUDIT_ARCH_S390
;;
powerpc64-*)
seccomp_audit_arch=AUDIT_ARCH_PPC64
;;
powerpc64le-*)
seccomp_audit_arch=AUDIT_ARCH_PPC64LE
;;
mips-*)
seccomp_audit_arch=AUDIT_ARCH_MIPS
;;
mipsel-*)
seccomp_audit_arch=AUDIT_ARCH_MIPSEL
;;
mips64-*)
case "$mips_abi" in
"n32")
seccomp_audit_arch=AUDIT_ARCH_MIPS64N32
;;
"n64")
seccomp_audit_arch=AUDIT_ARCH_MIPS64
;;
esac
;;
mips64el-*)
case "$mips_abi" in
"n32")
seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32
;;
"n64")
seccomp_audit_arch=AUDIT_ARCH_MIPSEL64
;;
esac
;;
esac
if test "x$seccomp_audit_arch" != "x" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: \"$seccomp_audit_arch\"" >&5
$as_echo "\"$seccomp_audit_arch\"" >&6; }
cat >>confdefs.h <<_ACEOF
#define SECCOMP_AUDIT_ARCH $seccomp_audit_arch
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: architecture not supported" >&5
$as_echo "architecture not supported" >&6; }
fi
;;
mips-sony-bsd|mips-sony-newsos4)
$as_echo "#define NEED_SETPGRP 1" >>confdefs.h
SONY=1
;;
*-*-netbsd*)
check_for_libcrypt_before=1
if test "x$withval" != "xno" ; then
- need_dash_r=1
+ rpath_opt="-R"
fi
CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE"
$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h
ac_fn_c_check_header_mongrel "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default"
if test "x$ac_cv_header_net_if_tap_h" = xyes; then :
else
$as_echo "#define SSH_TUN_NO_L2 1" >>confdefs.h
fi
$as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
TEST_MALLOC_OPTIONS="AJRX"
$as_echo "#define BROKEN_READ_COMPARISON 1" >>confdefs.h
;;
*-*-freebsd*)
check_for_libcrypt_later=1
$as_echo "#define LOCKED_PASSWD_PREFIX \"*LOCKED*\"" >>confdefs.h
$as_echo "#define SSH_TUN_FREEBSD 1" >>confdefs.h
ac_fn_c_check_header_mongrel "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default"
if test "x$ac_cv_header_net_if_tap_h" = xyes; then :
else
$as_echo "#define SSH_TUN_NO_L2 1" >>confdefs.h
fi
$as_echo "#define BROKEN_GLOB 1" >>confdefs.h
TEST_MALLOC_OPTIONS="AJRX"
# Preauth crypto occasionally uses file descriptors for crypto offload
# and will crash if they cannot be opened.
$as_echo "#define SANDBOX_SKIP_RLIMIT_NOFILE 1" >>confdefs.h
;;
*-*-bsdi*)
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
;;
*-next-*)
conf_lastlog_location="/usr/adm/lastlog"
conf_utmp_location=/etc/utmp
conf_wtmp_location=/usr/adm/wtmp
maildir=/usr/spool/mail
$as_echo "#define HAVE_NEXT 1" >>confdefs.h
$as_echo "#define BROKEN_REALPATH 1" >>confdefs.h
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define BROKEN_SAVED_UIDS 1" >>confdefs.h
;;
*-*-openbsd*)
use_pie=auto
$as_echo "#define HAVE_ATTRIBUTE__SENTINEL__ 1" >>confdefs.h
$as_echo "#define HAVE_ATTRIBUTE__BOUNDED__ 1" >>confdefs.h
$as_echo "#define SSH_TUN_OPENBSD 1" >>confdefs.h
$as_echo "#define SYSLOG_R_SAFE_IN_SIGHAND 1" >>confdefs.h
TEST_MALLOC_OPTIONS="AFGJPRX"
;;
*-*-solaris*)
if test "x$withval" != "xno" ; then
- need_dash_r=1
+ rpath_opt="-R"
fi
$as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
$as_echo "#define LOGIN_NEEDS_UTMPX 1" >>confdefs.h
$as_echo "#define PAM_TTY_KLUDGE 1" >>confdefs.h
$as_echo "#define SSHPAM_CHAUTHTOK_NEEDS_RUID 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
# Pushing STREAMS modules will cause sshd to acquire a controlling tty.
$as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
$as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h
external_path_file=/etc/default/login
# hardwire lastlog location (can't detect it on some versions)
conf_lastlog_location="/var/adm/lastlog"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for obsolete utmp and wtmp in solaris2.x" >&5
$as_echo_n "checking for obsolete utmp and wtmp in solaris2.x... " >&6; }
sol2ver=`echo "$host"| sed -e 's/.*[0-9]\.//'`
if test "$sol2ver" -ge 8; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
$as_echo "#define DISABLE_WTMP 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
for ac_func in setpflags
do :
ac_fn_c_check_func "$LINENO" "setpflags" "ac_cv_func_setpflags"
if test "x$ac_cv_func_setpflags" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SETPFLAGS 1
_ACEOF
fi
done
for ac_func in setppriv
do :
ac_fn_c_check_func "$LINENO" "setppriv" "ac_cv_func_setppriv"
if test "x$ac_cv_func_setppriv" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SETPPRIV 1
_ACEOF
fi
done
for ac_func in priv_basicset
do :
ac_fn_c_check_func "$LINENO" "priv_basicset" "ac_cv_func_priv_basicset"
if test "x$ac_cv_func_priv_basicset" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PRIV_BASICSET 1
_ACEOF
fi
done
for ac_header in priv.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "priv.h" "ac_cv_header_priv_h" "$ac_includes_default"
if test "x$ac_cv_header_priv_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PRIV_H 1
_ACEOF
fi
done
# Check whether --with-solaris-contracts was given.
if test "${with_solaris_contracts+set}" = set; then :
withval=$with_solaris_contracts;
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ct_tmpl_activate in -lcontract" >&5
$as_echo_n "checking for ct_tmpl_activate in -lcontract... " >&6; }
if ${ac_cv_lib_contract_ct_tmpl_activate+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcontract $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char ct_tmpl_activate ();
int
main ()
{
return ct_tmpl_activate ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_contract_ct_tmpl_activate=yes
else
ac_cv_lib_contract_ct_tmpl_activate=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_contract_ct_tmpl_activate" >&5
$as_echo "$ac_cv_lib_contract_ct_tmpl_activate" >&6; }
if test "x$ac_cv_lib_contract_ct_tmpl_activate" = xyes; then :
$as_echo "#define USE_SOLARIS_PROCESS_CONTRACTS 1" >>confdefs.h
LIBS="$LIBS -lcontract"
SPC_MSG="yes"
fi
fi
# Check whether --with-solaris-projects was given.
if test "${with_solaris_projects+set}" = set; then :
withval=$with_solaris_projects;
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for setproject in -lproject" >&5
$as_echo_n "checking for setproject in -lproject... " >&6; }
if ${ac_cv_lib_project_setproject+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lproject $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char setproject ();
int
main ()
{
return setproject ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_project_setproject=yes
else
ac_cv_lib_project_setproject=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_project_setproject" >&5
$as_echo "$ac_cv_lib_project_setproject" >&6; }
if test "x$ac_cv_lib_project_setproject" = xyes; then :
$as_echo "#define USE_SOLARIS_PROJECTS 1" >>confdefs.h
LIBS="$LIBS -lproject"
SP_MSG="yes"
fi
fi
# Check whether --with-solaris-privs was given.
if test "${with_solaris_privs+set}" = set; then :
withval=$with_solaris_privs;
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/Illumos privilege support" >&5
$as_echo_n "checking for Solaris/Illumos privilege support... " >&6; }
if test "x$ac_cv_func_setppriv" = "xyes" -a \
"x$ac_cv_header_priv_h" = "xyes" ; then
SOLARIS_PRIVS=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
$as_echo "found" >&6; }
$as_echo "#define NO_UID_RESTORATION_TEST 1" >>confdefs.h
$as_echo "#define USE_SOLARIS_PRIVS 1" >>confdefs.h
SPP_MSG="yes"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
as_fn_error $? "*** must have support for Solaris privileges to use --with-solaris-privs" "$LINENO" 5
fi
fi
TEST_SHELL=$SHELL # let configure find us a capable shell
;;
*-*-sunos4*)
CPPFLAGS="$CPPFLAGS -DSUNOS4"
for ac_func in getpwanam
do :
ac_fn_c_check_func "$LINENO" "getpwanam" "ac_cv_func_getpwanam"
if test "x$ac_cv_func_getpwanam" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GETPWANAM 1
_ACEOF
fi
done
$as_echo "#define PAM_SUN_CODEBASE 1" >>confdefs.h
conf_utmp_location=/etc/utmp
conf_wtmp_location=/var/adm/wtmp
conf_lastlog_location=/var/adm/lastlog
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define DISABLE_UTMPX 1" >>confdefs.h
;;
*-ncr-sysv*)
LIBS="$LIBS -lc89"
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
;;
*-sni-sysv*)
# /usr/ucblib MUST NOT be searched on ReliantUNIX
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5
$as_echo_n "checking for dlsym in -ldl... " >&6; }
if ${ac_cv_lib_dl_dlsym+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char dlsym ();
int
main ()
{
return dlsym ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dl_dlsym=yes
else
ac_cv_lib_dl_dlsym=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5
$as_echo "$ac_cv_lib_dl_dlsym" >&6; }
if test "x$ac_cv_lib_dl_dlsym" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBDL 1
_ACEOF
LIBS="-ldl $LIBS"
fi
# -lresolv needs to be at the end of LIBS or DNS lookups break
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5
$as_echo_n "checking for res_query in -lresolv... " >&6; }
if ${ac_cv_lib_resolv_res_query+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lresolv $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char res_query ();
int
main ()
{
return res_query ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_resolv_res_query=yes
else
ac_cv_lib_resolv_res_query=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_query" >&5
$as_echo "$ac_cv_lib_resolv_res_query" >&6; }
if test "x$ac_cv_lib_resolv_res_query" = xyes; then :
LIBS="$LIBS -lresolv"
fi
IPADDR_IN_DISPLAY=yes
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define IP_TOS_IS_BROKEN 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
external_path_file=/etc/default/login
# /usr/ucblib/libucb.a no longer needed on ReliantUNIX
# Attention: always take care to bind libsocket and libnsl before libc,
# otherwise you will find lots of "SIOCGPGRP errno 22" on syslog
;;
# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel.
*-*-sysv4.2*)
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
$as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
TEST_SHELL=$SHELL # let configure find us a capable shell
;;
# UnixWare 7.x, OpenUNIX 8
*-*-sysv5*)
CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf"
$as_echo "#define UNIXWARE_LONG_PASSWORDS 1" >>confdefs.h
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
$as_echo "#define BROKEN_TCGETATTR_ICANON 1" >>confdefs.h
TEST_SHELL=$SHELL # let configure find us a capable shell
check_for_libcrypt_later=1
case "$host" in
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
maildir=/var/spool/mail
$as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getluid in -lprot" >&5
$as_echo_n "checking for getluid in -lprot... " >&6; }
if ${ac_cv_lib_prot_getluid+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lprot $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char getluid ();
int
main ()
{
return getluid ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_prot_getluid=yes
else
ac_cv_lib_prot_getluid=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_prot_getluid" >&5
$as_echo "$ac_cv_lib_prot_getluid" >&6; }
if test "x$ac_cv_lib_prot_getluid" = xyes; then :
LIBS="$LIBS -lprot"
for ac_func in getluid setluid
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
fi
;;
*) $as_echo "#define LOCKED_PASSWD_STRING \"*LK*\"" >>confdefs.h
;;
esac
;;
*-*-sysv*)
;;
# SCO UNIX and OEM versions of SCO UNIX
*-*-sco3.2v4*)
as_fn_error $? "\"This Platform is no longer supported.\"" "$LINENO" 5
;;
# SCO OpenServer 5.x
*-*-sco3.2v5*)
if test -z "$GCC"; then
CFLAGS="$CFLAGS -belf"
fi
LIBS="$LIBS -lprot -lx -ltinfo -lm"
no_dev_ptmx=1
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define HAVE_SECUREWARE 1" >>confdefs.h
$as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
$as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define WITH_ABBREV_NO_TTY 1" >>confdefs.h
$as_echo "#define BROKEN_UPDWTMPX 1" >>confdefs.h
$as_echo "#define PASSWD_NEEDS_USERNAME 1" >>confdefs.h
for ac_func in getluid setluid
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
MANTYPE=man
TEST_SHELL=$SHELL # let configure find us a capable shell
SKIP_DISABLE_LASTLOG_DEFINE=yes
;;
*-dec-osf*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Digital Unix SIA" >&5
$as_echo_n "checking for Digital Unix SIA... " >&6; }
no_osfsia=""
# Check whether --with-osfsia was given.
if test "${with_osfsia+set}" = set; then :
withval=$with_osfsia;
if test "x$withval" = "xno" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
$as_echo "disabled" >&6; }
no_osfsia=1
fi
fi
if test -z "$no_osfsia" ; then
if test -f /etc/sia/matrix.conf; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_OSF_SIA 1" >>confdefs.h
$as_echo "#define DISABLE_LOGIN 1" >>confdefs.h
$as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
LIBS="$LIBS -lsecurity -ldb -lm -laud"
SIA_MSG="yes"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define LOCKED_PASSWD_SUBSTR \"Nologin\"" >>confdefs.h
fi
fi
$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREUID 1" >>confdefs.h
$as_echo "#define BROKEN_SETREGID 1" >>confdefs.h
$as_echo "#define BROKEN_READV_COMPARISON 1" >>confdefs.h
;;
*-*-nto-qnx*)
$as_echo "#define USE_PIPES 1" >>confdefs.h
$as_echo "#define NO_X11_UNIX_SOCKETS 1" >>confdefs.h
$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
$as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
$as_echo "#define BROKEN_SHADOW_EXPIRE 1" >>confdefs.h
enable_etc_default_login=no # has incompatible /etc/default/login
case "$host" in
*-*-nto-qnx6*)
$as_echo "#define DISABLE_FD_PASSING 1" >>confdefs.h
;;
esac
;;
*-*-ultrix*)
$as_echo "#define BROKEN_GETGROUPS 1" >>confdefs.h
$as_echo "#define NEED_SETPGRP 1" >>confdefs.h
$as_echo "#define HAVE_SYS_SYSLOG_H 1" >>confdefs.h
;;
*-*-lynxos)
CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
$as_echo "#define BROKEN_SETVBUF 1" >>confdefs.h
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler and flags for sanity" >&5
$as_echo_n "checking compiler and flags for sanity... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking compiler sanity" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking compiler sanity" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "*** compiler cannot create working executables, check config.log ***" "$LINENO" 5
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
# Checks for libraries.
ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt"
if test "x$ac_cv_func_setsockopt" = xyes; then :
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5
$as_echo_n "checking for setsockopt in -lsocket... " >&6; }
if ${ac_cv_lib_socket_setsockopt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char setsockopt ();
int
main ()
{
return setsockopt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_socket_setsockopt=yes
else
ac_cv_lib_socket_setsockopt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5
$as_echo "$ac_cv_lib_socket_setsockopt" >&6; }
if test "x$ac_cv_lib_socket_setsockopt" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBSOCKET 1
_ACEOF
LIBS="-lsocket $LIBS"
fi
fi
for ac_func in dirname
do :
ac_fn_c_check_func "$LINENO" "dirname" "ac_cv_func_dirname"
if test "x$ac_cv_func_dirname" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_DIRNAME 1
_ACEOF
for ac_header in libgen.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default"
if test "x$ac_cv_header_libgen_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBGEN_H 1
_ACEOF
fi
done
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dirname in -lgen" >&5
$as_echo_n "checking for dirname in -lgen... " >&6; }
if ${ac_cv_lib_gen_dirname+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgen $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char dirname ();
int
main ()
{
return dirname ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_gen_dirname=yes
else
ac_cv_lib_gen_dirname=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_dirname" >&5
$as_echo "$ac_cv_lib_gen_dirname" >&6; }
if test "x$ac_cv_lib_gen_dirname" = xyes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken dirname" >&5
$as_echo_n "checking for broken dirname... " >&6; }
if ${ac_cv_have_broken_dirname+:} false; then :
$as_echo_n "(cached) " >&6
else
save_LIBS="$LIBS"
LIBS="$LIBS -lgen"
if test "$cross_compiling" = yes; then :
ac_cv_have_broken_dirname="no"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <libgen.h>
#include <string.h>
int main(int argc, char **argv) {
char *s, buf[32];
strncpy(buf,"/etc", 32);
s = dirname(buf);
if (!s || strncmp(s, "/", 32) != 0) {
exit(1);
} else {
exit(0);
}
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_have_broken_dirname="no"
else
ac_cv_have_broken_dirname="yes"
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
LIBS="$save_LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_broken_dirname" >&5
$as_echo "$ac_cv_have_broken_dirname" >&6; }
if test "x$ac_cv_have_broken_dirname" = "xno" ; then
LIBS="$LIBS -lgen"
$as_echo "#define HAVE_DIRNAME 1" >>confdefs.h
for ac_header in libgen.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "libgen.h" "ac_cv_header_libgen_h" "$ac_includes_default"
if test "x$ac_cv_header_libgen_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBGEN_H 1
_ACEOF
fi
done
fi
fi
fi
done
ac_fn_c_check_func "$LINENO" "getspnam" "ac_cv_func_getspnam"
if test "x$ac_cv_func_getspnam" = xyes; then :
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getspnam in -lgen" >&5
$as_echo_n "checking for getspnam in -lgen... " >&6; }
if ${ac_cv_lib_gen_getspnam+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgen $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char getspnam ();
int
main ()
{
return getspnam ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_gen_getspnam=yes
else
ac_cv_lib_gen_getspnam=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_getspnam" >&5
$as_echo "$ac_cv_lib_gen_getspnam" >&6; }
if test "x$ac_cv_lib_gen_getspnam" = xyes; then :
LIBS="$LIBS -lgen"
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing basename" >&5
$as_echo_n "checking for library containing basename... " >&6; }
if ${ac_cv_search_basename+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char basename ();
int
main ()
{
return basename ();
;
return 0;
}
_ACEOF
for ac_lib in '' gen; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_basename=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_basename+:} false; then :
break
fi
done
if ${ac_cv_search_basename+:} false; then :
else
ac_cv_search_basename=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_basename" >&5
$as_echo "$ac_cv_search_basename" >&6; }
ac_res=$ac_cv_search_basename
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$as_echo "#define HAVE_BASENAME 1" >>confdefs.h
fi
# Check whether --with-zlib was given.
if test "${with_zlib+set}" = set; then :
withval=$with_zlib; if test "x$withval" = "xno" ; then
as_fn_error $? "*** zlib is required ***" "$LINENO" 5
elif test "x$withval" != "xyes"; then
if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}"
else
LDFLAGS="-L${withval} ${LDFLAGS}"
fi
fi
if test -d "$withval/include"; then
CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
else
CPPFLAGS="-I${withval} ${CPPFLAGS}"
fi
fi
fi
ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
if test "x$ac_cv_header_zlib_h" = xyes; then :
else
as_fn_error $? "*** zlib.h missing - please install first or check config.log ***" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5
$as_echo_n "checking for deflate in -lz... " >&6; }
if ${ac_cv_lib_z_deflate+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lz $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char deflate ();
int
main ()
{
return deflate ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_z_deflate=yes
else
ac_cv_lib_z_deflate=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5
$as_echo "$ac_cv_lib_z_deflate" >&6; }
if test "x$ac_cv_lib_z_deflate" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBZ 1
_ACEOF
LIBS="-lz $LIBS"
else
saved_CPPFLAGS="$CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
save_LIBS="$LIBS"
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/lib -R/usr/local/lib ${saved_LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}"
else
LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}"
fi
CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}"
LIBS="$LIBS -lz"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char deflate ();
int
main ()
{
return deflate ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
$as_echo "#define HAVE_LIBZ 1" >>confdefs.h
else
as_fn_error $? "*** zlib missing - please install first or check config.log ***" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
# Check whether --with-zlib-version-check was given.
if test "${with_zlib_version_check+set}" = set; then :
withval=$with_zlib_version_check; if test "x$withval" = "xno" ; then
zlib_check_nonfatal=1
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for possibly buggy zlib" >&5
$as_echo_n "checking for possibly buggy zlib... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking zlib version" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking zlib version" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
int
main ()
{
int a=0, b=0, c=0, d=0, n, v;
n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d);
if (n != 3 && n != 4)
exit(1);
v = a*1000000 + b*10000 + c*100 + d;
fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v);
/* 1.1.4 is OK */
if (a == 1 && b == 1 && c >= 4)
exit(0);
/* 1.2.3 and up are OK */
if (v >= 1020300)
exit(0);
exit(2);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
if test -z "$zlib_check_nonfatal" ; then
as_fn_error $? "*** zlib too old - check config.log ***
Your reported zlib version has known security problems. It's possible your
vendor has fixed these problems without changing the version number. If you
are sure this is the case, you can disable the check by running
\"./configure --without-zlib-version-check\".
If you are in doubt, upgrade zlib to version 1.2.3 or greater.
See http://www.gzip.org/zlib/ for details." "$LINENO" 5
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zlib version may have security problems" >&5
$as_echo "$as_me: WARNING: zlib version may have security problems" >&2;}
fi
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp"
if test "x$ac_cv_func_strcasecmp" = xyes; then :
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strcasecmp in -lresolv" >&5
$as_echo_n "checking for strcasecmp in -lresolv... " >&6; }
if ${ac_cv_lib_resolv_strcasecmp+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lresolv $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char strcasecmp ();
int
main ()
{
return strcasecmp ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_resolv_strcasecmp=yes
else
ac_cv_lib_resolv_strcasecmp=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_strcasecmp" >&5
$as_echo "$ac_cv_lib_resolv_strcasecmp" >&6; }
if test "x$ac_cv_lib_resolv_strcasecmp" = xyes; then :
LIBS="$LIBS -lresolv"
fi
fi
for ac_func in utimes
do :
ac_fn_c_check_func "$LINENO" "utimes" "ac_cv_func_utimes"
if test "x$ac_cv_func_utimes" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UTIMES 1
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for utimes in -lc89" >&5
$as_echo_n "checking for utimes in -lc89... " >&6; }
if ${ac_cv_lib_c89_utimes+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lc89 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char utimes ();
int
main ()
{
return utimes ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_c89_utimes=yes
else
ac_cv_lib_c89_utimes=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_utimes" >&5
$as_echo "$ac_cv_lib_c89_utimes" >&6; }
if test "x$ac_cv_lib_c89_utimes" = xyes; then :
$as_echo "#define HAVE_UTIMES 1" >>confdefs.h
LIBS="$LIBS -lc89"
fi
fi
done
for ac_header in bsd/libutil.h libutil.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fmt_scaled" >&5
$as_echo_n "checking for library containing fmt_scaled... " >&6; }
if ${ac_cv_search_fmt_scaled+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char fmt_scaled ();
int
main ()
{
return fmt_scaled ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_fmt_scaled=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_fmt_scaled+:} false; then :
break
fi
done
if ${ac_cv_search_fmt_scaled+:} false; then :
else
ac_cv_search_fmt_scaled=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fmt_scaled" >&5
$as_echo "$ac_cv_search_fmt_scaled" >&6; }
ac_res=$ac_cv_search_fmt_scaled
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing scan_scaled" >&5
$as_echo_n "checking for library containing scan_scaled... " >&6; }
if ${ac_cv_search_scan_scaled+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char scan_scaled ();
int
main ()
{
return scan_scaled ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_scan_scaled=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_scan_scaled+:} false; then :
break
fi
done
if ${ac_cv_search_scan_scaled+:} false; then :
else
ac_cv_search_scan_scaled=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_scan_scaled" >&5
$as_echo "$ac_cv_search_scan_scaled" >&6; }
ac_res=$ac_cv_search_scan_scaled
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing login" >&5
$as_echo_n "checking for library containing login... " >&6; }
if ${ac_cv_search_login+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char login ();
int
main ()
{
return login ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_login=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_login+:} false; then :
break
fi
done
if ${ac_cv_search_login+:} false; then :
else
ac_cv_search_login=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_login" >&5
$as_echo "$ac_cv_search_login" >&6; }
ac_res=$ac_cv_search_login
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing logout" >&5
$as_echo_n "checking for library containing logout... " >&6; }
if ${ac_cv_search_logout+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char logout ();
int
main ()
{
return logout ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_logout=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_logout+:} false; then :
break
fi
done
if ${ac_cv_search_logout+:} false; then :
else
ac_cv_search_logout=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logout" >&5
$as_echo "$ac_cv_search_logout" >&6; }
ac_res=$ac_cv_search_logout
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing logwtmp" >&5
$as_echo_n "checking for library containing logwtmp... " >&6; }
if ${ac_cv_search_logwtmp+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char logwtmp ();
int
main ()
{
return logwtmp ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_logwtmp=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_logwtmp+:} false; then :
break
fi
done
if ${ac_cv_search_logwtmp+:} false; then :
else
ac_cv_search_logwtmp=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_logwtmp" >&5
$as_echo "$ac_cv_search_logwtmp" >&6; }
ac_res=$ac_cv_search_logwtmp
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing openpty" >&5
$as_echo_n "checking for library containing openpty... " >&6; }
if ${ac_cv_search_openpty+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char openpty ();
int
main ()
{
return openpty ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_openpty=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_openpty+:} false; then :
break
fi
done
if ${ac_cv_search_openpty+:} false; then :
else
ac_cv_search_openpty=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_openpty" >&5
$as_echo "$ac_cv_search_openpty" >&6; }
ac_res=$ac_cv_search_openpty
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing updwtmp" >&5
$as_echo_n "checking for library containing updwtmp... " >&6; }
if ${ac_cv_search_updwtmp+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char updwtmp ();
int
main ()
{
return updwtmp ();
;
return 0;
}
_ACEOF
for ac_lib in '' util bsd; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_updwtmp=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_updwtmp+:} false; then :
break
fi
done
if ${ac_cv_search_updwtmp+:} false; then :
else
ac_cv_search_updwtmp=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_updwtmp" >&5
$as_echo "$ac_cv_search_updwtmp" >&6; }
ac_res=$ac_cv_search_updwtmp
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
for ac_func in fmt_scaled scan_scaled login logout openpty updwtmp logwtmp
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
# On some platforms, inet_ntop and gethostbyname may be found in libresolv
# or libnsl.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntop" >&5
$as_echo_n "checking for library containing inet_ntop... " >&6; }
if ${ac_cv_search_inet_ntop+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char inet_ntop ();
int
main ()
{
return inet_ntop ();
;
return 0;
}
_ACEOF
for ac_lib in '' resolv nsl; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_inet_ntop=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_inet_ntop+:} false; then :
break
fi
done
if ${ac_cv_search_inet_ntop+:} false; then :
else
ac_cv_search_inet_ntop=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntop" >&5
$as_echo "$ac_cv_search_inet_ntop" >&6; }
ac_res=$ac_cv_search_inet_ntop
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
$as_echo_n "checking for library containing gethostbyname... " >&6; }
if ${ac_cv_search_gethostbyname+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char gethostbyname ();
int
main ()
{
return gethostbyname ();
;
return 0;
}
_ACEOF
for ac_lib in '' resolv nsl; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_gethostbyname=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_gethostbyname+:} false; then :
break
fi
done
if ${ac_cv_search_gethostbyname+:} false; then :
else
ac_cv_search_gethostbyname=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
$as_echo "$ac_cv_search_gethostbyname" >&6; }
ac_res=$ac_cv_search_gethostbyname
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
# "Particular Function Checks"
# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
for ac_func in strftime
do :
ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime"
if test "x$ac_cv_func_strftime" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRFTIME 1
_ACEOF
else
# strftime is in -lintl on SCO UNIX.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5
$as_echo_n "checking for strftime in -lintl... " >&6; }
if ${ac_cv_lib_intl_strftime+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lintl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char strftime ();
int
main ()
{
return strftime ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_intl_strftime=yes
else
ac_cv_lib_intl_strftime=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5
$as_echo "$ac_cv_lib_intl_strftime" >&6; }
if test "x$ac_cv_lib_intl_strftime" = xyes; then :
$as_echo "#define HAVE_STRFTIME 1" >>confdefs.h
LIBS="-lintl $LIBS"
fi
fi
done
for ac_header in stdlib.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
if test "x$ac_cv_header_stdlib_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STDLIB_H 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
if ${ac_cv_func_malloc_0_nonnull+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
ac_cv_func_malloc_0_nonnull=no
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if defined STDC_HEADERS || defined HAVE_STDLIB_H
# include <stdlib.h>
#else
char *malloc ();
#endif
int
main ()
{
return ! malloc (0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_func_malloc_0_nonnull=yes
else
ac_cv_func_malloc_0_nonnull=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
if test $ac_cv_func_malloc_0_nonnull = yes; then :
$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
else
$as_echo "#define HAVE_MALLOC 0" >>confdefs.h
case " $LIBOBJS " in
*" malloc.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS malloc.$ac_objext"
;;
esac
$as_echo "#define malloc rpl_malloc" >>confdefs.h
fi
for ac_header in stdlib.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
if test "x$ac_cv_header_stdlib_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STDLIB_H 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5
$as_echo_n "checking for GNU libc compatible realloc... " >&6; }
if ${ac_cv_func_realloc_0_nonnull+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
ac_cv_func_realloc_0_nonnull=no
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if defined STDC_HEADERS || defined HAVE_STDLIB_H
# include <stdlib.h>
#else
char *realloc ();
#endif
int
main ()
{
return ! realloc (0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_func_realloc_0_nonnull=yes
else
ac_cv_func_realloc_0_nonnull=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5
$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; }
if test $ac_cv_func_realloc_0_nonnull = yes; then :
$as_echo "#define HAVE_REALLOC 1" >>confdefs.h
else
$as_echo "#define HAVE_REALLOC 0" >>confdefs.h
case " $LIBOBJS " in
*" realloc.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS realloc.$ac_objext"
;;
esac
$as_echo "#define realloc rpl_realloc" >>confdefs.h
fi
# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL;
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if calloc(0, N) returns non-null" >&5
$as_echo_n "checking if calloc(0, N) returns non-null... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming same as malloc" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming same as malloc" >&2;}
func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
int
main ()
{
void *p = calloc(0, 1); exit(p == NULL);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
func_calloc_0_nonnull=yes
else
func_calloc_0_nonnull=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $func_calloc_0_nonnull" >&5
$as_echo "$func_calloc_0_nonnull" >&6; }
if test "x$func_calloc_0_nonnull" = "xyes"; then
$as_echo "#define HAVE_CALLOC 1" >>confdefs.h
else
$as_echo "#define HAVE_CALLOC 0" >>confdefs.h
$as_echo "#define calloc rpl_calloc" >>confdefs.h
fi
# Check for ALTDIRFUNC glob() extension
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLOB_ALTDIRFUNC support" >&5
$as_echo_n "checking for GLOB_ALTDIRFUNC support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <glob.h>
#ifdef GLOB_ALTDIRFUNC
FOUNDIT
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "FOUNDIT" >/dev/null 2>&1; then :
$as_echo "#define GLOB_HAS_ALTDIRFUNC 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f conftest*
# Check for g.gl_matchc glob() extension
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gl_matchc field in glob_t" >&5
$as_echo_n "checking for gl_matchc field in glob_t... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <glob.h>
int
main ()
{
glob_t g; g.gl_matchc = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define GLOB_HAS_GL_MATCHC 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Check for g.gl_statv glob() extension
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gl_statv and GLOB_KEEPSTAT extensions for glob" >&5
$as_echo_n "checking for gl_statv and GLOB_KEEPSTAT extensions for glob... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <glob.h>
int
main ()
{
#ifndef GLOB_KEEPSTAT
#error "glob does not support GLOB_KEEPSTAT extension"
#endif
glob_t g;
g.gl_statv = NULL;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define GLOB_HAS_GL_STATV 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_fn_c_check_decl "$LINENO" "GLOB_NOMATCH" "ac_cv_have_decl_GLOB_NOMATCH" "#include <glob.h>
"
if test "x$ac_cv_have_decl_GLOB_NOMATCH" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GLOB_NOMATCH $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "VIS_ALL" "ac_cv_have_decl_VIS_ALL" "#include <vis.h>
"
if test "x$ac_cv_have_decl_VIS_ALL" = xyes; then :
else
$as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct dirent allocates space for d_name" >&5
$as_echo_n "checking whether struct dirent allocates space for d_name... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME" >&2;}
$as_echo "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <dirent.h>
int
main ()
{
struct dirent d;
exit(sizeof(d.d_name)<=sizeof(char));
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_ONE_BYTE_DIRENT_D_NAME 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for /proc/pid/fd directory" >&5
$as_echo_n "checking for /proc/pid/fd directory... " >&6; }
if test -d "/proc/$$/fd" ; then
$as_echo "#define HAVE_PROC_PID 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Check whether user wants to use ldns
LDNS_MSG="no"
# Check whether --with-ldns was given.
if test "${with_ldns+set}" = set; then :
withval=$with_ldns;
ldns=""
if test "x$withval" = "xyes" ; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ldns-config", so it can be a program name with args.
set dummy ${ac_tool_prefix}ldns-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_LDNSCONFIG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $LDNSCONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_LDNSCONFIG="$LDNSCONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_LDNSCONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
LDNSCONFIG=$ac_cv_path_LDNSCONFIG
if test -n "$LDNSCONFIG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDNSCONFIG" >&5
$as_echo "$LDNSCONFIG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$ac_cv_path_LDNSCONFIG"; then
ac_pt_LDNSCONFIG=$LDNSCONFIG
# Extract the first word of "ldns-config", so it can be a program name with args.
set dummy ldns-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_ac_pt_LDNSCONFIG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $ac_pt_LDNSCONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_LDNSCONFIG="$ac_pt_LDNSCONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_ac_pt_LDNSCONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
ac_pt_LDNSCONFIG=$ac_cv_path_ac_pt_LDNSCONFIG
if test -n "$ac_pt_LDNSCONFIG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_LDNSCONFIG" >&5
$as_echo "$ac_pt_LDNSCONFIG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$ac_pt_LDNSCONFIG" = x; then
LDNSCONFIG="no"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
LDNSCONFIG=$ac_pt_LDNSCONFIG
fi
else
LDNSCONFIG="$ac_cv_path_LDNSCONFIG"
fi
if test "x$LDNSCONFIG" = "xno"; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBS="-lldns $LIBS"
ldns=yes
else
LIBS="$LIBS `$LDNSCONFIG --libs`"
CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
ldns=yes
fi
elif test "x$withval" != "xno" ; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBS="-lldns $LIBS"
ldns=yes
fi
# Verify that it works.
if test "x$ldns" = "xyes" ; then
$as_echo "#define HAVE_LDNS 1" >>confdefs.h
LDNS_MSG="yes"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ldns support" >&5
$as_echo_n "checking for ldns support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ldns/ldns.h>
int main() { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); }
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "** Incomplete or missing ldns libraries." "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
fi
# Check whether user wants libedit support
LIBEDIT_MSG="no"
# Check whether --with-libedit was given.
if test "${with_libedit+set}" = set; then :
withval=$with_libedit; if test "x$withval" != "xno" ; then
if test "x$withval" = "xyes" ; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PKGCONFIG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $PKGCONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PKGCONFIG=$ac_cv_path_PKGCONFIG
if test -n "$PKGCONFIG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
$as_echo "$PKGCONFIG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$ac_cv_path_PKGCONFIG"; then
ac_pt_PKGCONFIG=$PKGCONFIG
# Extract the first word of "pkg-config", so it can be a program name with args.
set dummy pkg-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_ac_pt_PKGCONFIG+:} false; then :
$as_echo_n "(cached) " >&6
else
case $ac_pt_PKGCONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_ac_pt_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG
if test -n "$ac_pt_PKGCONFIG"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5
$as_echo "$ac_pt_PKGCONFIG" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$ac_pt_PKGCONFIG" = x; then
PKGCONFIG="no"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
PKGCONFIG=$ac_pt_PKGCONFIG
fi
else
PKGCONFIG="$ac_cv_path_PKGCONFIG"
fi
if test "x$PKGCONFIG" != "xno"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $PKGCONFIG knows about libedit" >&5
$as_echo_n "checking if $PKGCONFIG knows about libedit... " >&6; }
if "$PKGCONFIG" libedit; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
use_pkgconfig_for_libedit=yes
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
else
CPPFLAGS="$CPPFLAGS -I${withval}/include"
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
fi
if test "x$use_pkgconfig_for_libedit" = "xyes"; then
LIBEDIT=`$PKGCONFIG --libs libedit`
CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`"
else
LIBEDIT="-ledit -lcurses"
fi
OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for el_init in -ledit" >&5
$as_echo_n "checking for el_init in -ledit... " >&6; }
if ${ac_cv_lib_edit_el_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ledit $OTHERLIBS
$LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char el_init ();
int
main ()
{
return el_init ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_edit_el_init=yes
else
ac_cv_lib_edit_el_init=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_el_init" >&5
$as_echo "$ac_cv_lib_edit_el_init" >&6; }
if test "x$ac_cv_lib_edit_el_init" = xyes; then :
$as_echo "#define USE_LIBEDIT 1" >>confdefs.h
LIBEDIT_MSG="yes"
else
as_fn_error $? "libedit not found" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libedit version is compatible" >&5
$as_echo_n "checking if libedit version is compatible... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <histedit.h>
int
main ()
{
int i = H_SETSIZE;
el_init("", NULL, NULL, NULL);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
as_fn_error $? "libedit version is not compatible" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
fi
AUDIT_MODULE=none
# Check whether --with-audit was given.
if test "${with_audit+set}" = set; then :
withval=$with_audit;
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for supported audit module" >&5
$as_echo_n "checking for supported audit module... " >&6; }
case "$withval" in
bsm)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: bsm" >&5
$as_echo "bsm" >&6; }
AUDIT_MODULE=bsm
for ac_header in bsm/audit.h
do :
ac_fn_c_check_header_compile "$LINENO" "bsm/audit.h" "ac_cv_header_bsm_audit_h" "
#ifdef HAVE_TIME_H
# include <time.h>
#endif
"
if test "x$ac_cv_header_bsm_audit_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_BSM_AUDIT_H 1
_ACEOF
else
as_fn_error $? "BSM enabled and bsm/audit.h not found" "$LINENO" 5
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaudit in -lbsm" >&5
$as_echo_n "checking for getaudit in -lbsm... " >&6; }
if ${ac_cv_lib_bsm_getaudit+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lbsm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char getaudit ();
int
main ()
{
return getaudit ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_bsm_getaudit=yes
else
ac_cv_lib_bsm_getaudit=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsm_getaudit" >&5
$as_echo "$ac_cv_lib_bsm_getaudit" >&6; }
if test "x$ac_cv_lib_bsm_getaudit" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBBSM 1
_ACEOF
LIBS="-lbsm $LIBS"
else
as_fn_error $? "BSM enabled and required library not found" "$LINENO" 5
fi
for ac_func in getaudit
do :
ac_fn_c_check_func "$LINENO" "getaudit" "ac_cv_func_getaudit"
if test "x$ac_cv_func_getaudit" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GETAUDIT 1
_ACEOF
else
as_fn_error $? "BSM enabled and required function not found" "$LINENO" 5
fi
done
# These are optional
for ac_func in getaudit_addr aug_get_machine
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
$as_echo "#define USE_BSM_AUDIT 1" >>confdefs.h
if test "$sol2ver" -ge 11; then
SSHDLIBS="$SSHDLIBS -lscf"
$as_echo "#define BROKEN_BSM_API 1" >>confdefs.h
fi
;;
linux)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: linux" >&5
$as_echo "linux" >&6; }
AUDIT_MODULE=linux
for ac_header in libaudit.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "libaudit.h" "ac_cv_header_libaudit_h" "$ac_includes_default"
if test "x$ac_cv_header_libaudit_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBAUDIT_H 1
_ACEOF
fi
done
SSHDLIBS="$SSHDLIBS -laudit"
$as_echo "#define USE_LINUX_AUDIT 1" >>confdefs.h
;;
debug)
AUDIT_MODULE=debug
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
$as_echo "debug" >&6; }
$as_echo "#define SSH_AUDIT_EVENTS 1" >>confdefs.h
;;
no)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
;;
*)
as_fn_error $? "Unknown audit module $withval" "$LINENO" 5
;;
esac
fi
# Check whether --with-pie was given.
if test "${with_pie+set}" = set; then :
withval=$with_pie;
if test "x$withval" = "xno"; then
use_pie=no
fi
if test "x$withval" = "xyes"; then
use_pie=yes
fi
fi
if test "x$use_pie" = "x"; then
use_pie=no
fi
if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then
# Turn off automatic PIE when toolchain hardening is off.
use_pie=no
fi
if test "x$use_pie" = "xauto"; then
# Automatic PIE requires gcc >= 4.x
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc >= 4.x" >&5
$as_echo_n "checking for gcc >= 4.x... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#if !defined(__GNUC__) || __GNUC__ < 4
#error gcc is too old
#endif
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
use_pie=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x$use_pie" != "xno"; then
SAVED_CFLAGS="$CFLAGS"
SAVED_LDFLAGS="$LDFLAGS"
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fPIE" >&5
$as_echo_n "checking if $CC supports compile flag -fPIE... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $WERROR -fPIE"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-fPIE"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
exit(0);
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
CFLAGS="$saved_CFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$saved_CFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
}
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -pie" >&5
$as_echo_n "checking if $LD supports link flag -pie... " >&6; }
saved_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS $WERROR -pie"
_define_flag=""
test "x$_define_flag" = "x" && _define_flag="-pie"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
long long p = n * o;
printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p);
exit(0);
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
LDFLAGS="$saved_LDFLAGS $_define_flag"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LDFLAGS="$saved_LDFLAGS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
}
# We use both -fPIE and -pie or neither.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether both -fPIE and -pie are supported" >&5
$as_echo_n "checking whether both -fPIE and -pie are supported... " >&6; }
if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \
echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
CFLAGS="$SAVED_CFLAGS"
LDFLAGS="$SAVED_LDFLAGS"
fi
fi
for ac_func in \
Blowfish_initstate \
Blowfish_expandstate \
Blowfish_expand0state \
Blowfish_stream2word \
asprintf \
b64_ntop \
__b64_ntop \
b64_pton \
__b64_pton \
bcopy \
bcrypt_pbkdf \
bindresvport_sa \
blf_enc \
bzero \
cap_rights_limit \
clock \
closefrom \
dirfd \
endgrent \
err \
errx \
explicit_bzero \
fchmod \
+ fchmodat \
fchown \
+ fchownat \
flock \
freeaddrinfo \
freezero \
fstatfs \
fstatvfs \
futimes \
getaddrinfo \
getcwd \
getgrouplist \
getline \
getnameinfo \
getopt \
getpagesize \
getpeereid \
getpeerucred \
getpgid \
_getpty \
getrlimit \
getrandom \
getsid \
getttyent \
glob \
group_from_gid \
inet_aton \
inet_ntoa \
inet_ntop \
innetgr \
llabs \
login_getcapbool \
md5_crypt \
memmove \
memset_s \
mkdtemp \
ngetaddrinfo \
nsleep \
ogetaddrinfo \
openlog_r \
pledge \
poll \
prctl \
pstat \
raise \
readpassphrase \
reallocarray \
recvmsg \
recallocarray \
rresvport_af \
sendmsg \
setdtablesize \
setegid \
setenv \
seteuid \
setgroupent \
setgroups \
setlinebuf \
setlogin \
setpassent\
setpcred \
setproctitle \
setregid \
setreuid \
setrlimit \
setsid \
setvbuf \
sigaction \
sigvec \
snprintf \
socketpair \
statfs \
statvfs \
strcasestr \
strdup \
strerror \
strlcat \
strlcpy \
strmode \
strndup \
strnlen \
strnvis \
strptime \
strsignal \
strtonum \
strtoll \
strtoul \
strtoull \
swap32 \
sysconf \
tcgetpgrp \
timingsafe_bcmp \
truncate \
unsetenv \
updwtmpx \
+ utimensat \
user_from_uid \
usleep \
vasprintf \
vsnprintf \
waitpid \
warn \
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
ac_fn_c_check_decl "$LINENO" "bzero" "ac_cv_have_decl_bzero" "$ac_includes_default"
if test "x$ac_cv_have_decl_bzero" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_BZERO $ac_have_decl
_ACEOF
for ac_func in mblen mbtowc nl_langinfo wcwidth
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8 locale support" >&5
$as_echo_n "checking for utf8 locale support... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <locale.h>
#include <stdlib.h>
int
main ()
{
char *loc = setlocale(LC_CTYPE, "en_US.UTF-8");
if (loc != NULL)
exit(0);
exit(1);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
TEST_SSH_UTF8=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <ctype.h>
int
main ()
{
return (isblank('a'));
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
$as_echo "#define HAVE_ISBLANK 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
disable_pkcs11=
# Check whether --enable-pkcs11 was given.
if test "${enable_pkcs11+set}" = set; then :
enableval=$enable_pkcs11;
if test "x$enableval" = "xno" ; then
disable_pkcs11=1
fi
fi
# PKCS11 depends on OpenSSL.
if test "x$openssl" = "xyes" && test "x$disable_pkcs11" = "x"; then
# PKCS#11 support requires dlopen() and co
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
$as_echo_n "checking for library containing dlopen... " >&6; }
if ${ac_cv_search_dlopen+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char dlopen ();
int
main ()
{
return dlopen ();
;
return 0;
}
_ACEOF
for ac_lib in '' dl; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_dlopen=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_dlopen+:} false; then :
break
fi
done
if ${ac_cv_search_dlopen+:} false; then :
else
ac_cv_search_dlopen=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
$as_echo "$ac_cv_search_dlopen" >&6; }
ac_res=$ac_cv_search_dlopen
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
ac_fn_c_check_decl "$LINENO" "RTLD_NOW" "ac_cv_have_decl_RTLD_NOW" "#include <dlfcn.h>
"
if test "x$ac_cv_have_decl_RTLD_NOW" = xyes; then :
$as_echo "#define ENABLE_PKCS11 /**/" >>confdefs.h
fi
fi
fi
# IRIX has a const char return value for gai_strerror()
for ac_func in gai_strerror
do :
ac_fn_c_check_func "$LINENO" "gai_strerror" "ac_cv_func_gai_strerror"
if test "x$ac_cv_func_gai_strerror" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GAI_STRERROR 1
_ACEOF
$as_echo "#define HAVE_GAI_STRERROR 1" >>confdefs.h
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
const char *gai_strerror(int);
int
main ()
{
char *str;
str = gai_strerror(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_CONST_GAI_STRERROR_PROTO 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5
$as_echo_n "checking for library containing nanosleep... " >&6; }
if ${ac_cv_search_nanosleep+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char nanosleep ();
int
main ()
{
return nanosleep ();
;
return 0;
}
_ACEOF
for ac_lib in '' rt posix4; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_nanosleep=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_nanosleep+:} false; then :
break
fi
done
if ${ac_cv_search_nanosleep+:} false; then :
else
ac_cv_search_nanosleep=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5
$as_echo "$ac_cv_search_nanosleep" >&6; }
ac_res=$ac_cv_search_nanosleep
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$as_echo "#define HAVE_NANOSLEEP 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
$as_echo_n "checking for library containing clock_gettime... " >&6; }
if ${ac_cv_search_clock_gettime+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char clock_gettime ();
int
main ()
{
return clock_gettime ();
;
return 0;
}
_ACEOF
for ac_lib in '' rt; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_clock_gettime=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_clock_gettime+:} false; then :
break
fi
done
if ${ac_cv_search_clock_gettime+:} false; then :
else
ac_cv_search_clock_gettime=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
$as_echo "$ac_cv_search_clock_gettime" >&6; }
ac_res=$ac_cv_search_clock_gettime
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
fi
ac_fn_c_check_decl "$LINENO" "strsep" "ac_cv_have_decl_strsep" "
#ifdef HAVE_STRING_H
# include <string.h>
#endif
"
if test "x$ac_cv_have_decl_strsep" = xyes; then :
for ac_func in strsep
do :
ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep"
if test "x$ac_cv_func_strsep" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRSEP 1
_ACEOF
fi
done
fi
ac_fn_c_check_decl "$LINENO" "tcsendbreak" "ac_cv_have_decl_tcsendbreak" "#include <termios.h>
"
if test "x$ac_cv_have_decl_tcsendbreak" = xyes; then :
$as_echo "#define HAVE_TCSENDBREAK 1" >>confdefs.h
else
for ac_func in tcsendbreak
do :
ac_fn_c_check_func "$LINENO" "tcsendbreak" "ac_cv_func_tcsendbreak"
if test "x$ac_cv_func_tcsendbreak" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_TCSENDBREAK 1
_ACEOF
fi
done
fi
ac_fn_c_check_decl "$LINENO" "h_errno" "ac_cv_have_decl_h_errno" "#include <netdb.h>
"
if test "x$ac_cv_have_decl_h_errno" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_H_ERRNO $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "SHUT_RD" "ac_cv_have_decl_SHUT_RD" "
#include <sys/types.h>
#include <sys/socket.h>
"
if test "x$ac_cv_have_decl_SHUT_RD" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_SHUT_RD $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "O_NONBLOCK" "ac_cv_have_decl_O_NONBLOCK" "
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
"
if test "x$ac_cv_have_decl_O_NONBLOCK" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_O_NONBLOCK $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "readv" "ac_cv_have_decl_readv" "
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
"
if test "x$ac_cv_have_decl_readv" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_READV $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "writev" "ac_cv_have_decl_writev" "
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
"
if test "x$ac_cv_have_decl_writev" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_WRITEV $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "MAXSYMLINKS" "ac_cv_have_decl_MAXSYMLINKS" "
#include <sys/param.h>
"
if test "x$ac_cv_have_decl_MAXSYMLINKS" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_MAXSYMLINKS $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "offsetof" "ac_cv_have_decl_offsetof" "
#include <stddef.h>
"
if test "x$ac_cv_have_decl_offsetof" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_OFFSETOF $ac_have_decl
_ACEOF
# extra bits for select(2)
ac_fn_c_check_decl "$LINENO" "howmany" "ac_cv_have_decl_howmany" "
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SYSMACROS_H
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
"
if test "x$ac_cv_have_decl_howmany" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_HOWMANY $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "NFDBITS" "ac_cv_have_decl_NFDBITS" "
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SYSMACROS_H
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
"
if test "x$ac_cv_have_decl_NFDBITS" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_NFDBITS $ac_have_decl
_ACEOF
ac_fn_c_check_type "$LINENO" "fd_mask" "ac_cv_type_fd_mask" "
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
"
if test "x$ac_cv_type_fd_mask" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FD_MASK 1
_ACEOF
fi
for ac_func in setresuid
do :
ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid"
if test "x$ac_cv_func_setresuid" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SETRESUID 1
_ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if setresuid seems to work" >&5
$as_echo_n "checking if setresuid seems to work... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking setresuid" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <errno.h>
int
main ()
{
errno=0;
setresuid(0,0,0);
if (errno==ENOSYS)
exit(1);
else
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
$as_echo "#define BROKEN_SETRESUID 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5
$as_echo "not implemented" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
done
for ac_func in setresgid
do :
ac_fn_c_check_func "$LINENO" "setresgid" "ac_cv_func_setresgid"
if test "x$ac_cv_func_setresgid" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SETRESGID 1
_ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if setresgid seems to work" >&5
$as_echo_n "checking if setresgid seems to work... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking setresuid" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking setresuid" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <errno.h>
int
main ()
{
errno=0;
setresgid(0,0,0);
if (errno==ENOSYS)
exit(1);
else
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
$as_echo "#define BROKEN_SETRESGID 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not implemented" >&5
$as_echo "not implemented" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
done
for ac_func in realpath
do :
ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath"
if test "x$ac_cv_func_realpath" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_REALPATH 1
_ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if realpath works with non-existent files" >&5
$as_echo_n "checking if realpath works with non-existent files... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming working" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
int
main ()
{
char buf[PATH_MAX];
if (realpath("/opensshnonexistentfilename1234", buf) == NULL)
if (errno == ENOENT)
exit(1);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
$as_echo "#define BROKEN_REALPATH 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fflush(NULL)" >&5
$as_echo_n "checking for working fflush(NULL)... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming working" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming working" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
fflush(NULL); exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define FFLUSH_NULL_BUG 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
for ac_func in gettimeofday time
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_func in endutent getutent getutid getutline pututline setutent
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_func in utmpname
do :
ac_fn_c_check_func "$LINENO" "utmpname" "ac_cv_func_utmpname"
if test "x$ac_cv_func_utmpname" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UTMPNAME 1
_ACEOF
fi
done
for ac_func in endutxent getutxent getutxid getutxline getutxuser pututxline
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_func in setutxdb setutxent utmpxname
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_func in getlastlogxbyname
do :
ac_fn_c_check_func "$LINENO" "getlastlogxbyname" "ac_cv_func_getlastlogxbyname"
if test "x$ac_cv_func_getlastlogxbyname" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GETLASTLOGXBYNAME 1
_ACEOF
fi
done
ac_fn_c_check_func "$LINENO" "daemon" "ac_cv_func_daemon"
if test "x$ac_cv_func_daemon" = xyes; then :
$as_echo "#define HAVE_DAEMON 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for daemon in -lbsd" >&5
$as_echo_n "checking for daemon in -lbsd... " >&6; }
if ${ac_cv_lib_bsd_daemon+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lbsd $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char daemon ();
int
main ()
{
return daemon ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_bsd_daemon=yes
else
ac_cv_lib_bsd_daemon=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_daemon" >&5
$as_echo "$ac_cv_lib_bsd_daemon" >&6; }
if test "x$ac_cv_lib_bsd_daemon" = xyes; then :
LIBS="$LIBS -lbsd"; $as_echo "#define HAVE_DAEMON 1" >>confdefs.h
fi
fi
ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize"
if test "x$ac_cv_func_getpagesize" = xyes; then :
$as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpagesize in -lucb" >&5
$as_echo_n "checking for getpagesize in -lucb... " >&6; }
if ${ac_cv_lib_ucb_getpagesize+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lucb $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char getpagesize ();
int
main ()
{
return getpagesize ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_ucb_getpagesize=yes
else
ac_cv_lib_ucb_getpagesize=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ucb_getpagesize" >&5
$as_echo "$ac_cv_lib_ucb_getpagesize" >&6; }
if test "x$ac_cv_lib_ucb_getpagesize" = xyes; then :
LIBS="$LIBS -lucb"; $as_echo "#define HAVE_GETPAGESIZE 1" >>confdefs.h
fi
fi
# Check for broken snprintf
if test "x$ac_cv_func_snprintf" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf correctly terminates long strings" >&5
$as_echo_n "checking whether snprintf correctly terminates long strings... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5
$as_echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
char b[5];
snprintf(b,5,"123456789");
exit(b[4]!='\0');
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&5
$as_echo "$as_me: WARNING: ****** Your snprintf() function is broken, complain to your vendor" >&2;}
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
if test "x$ac_cv_func_snprintf" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf understands %zu" >&5
$as_echo_n "checking whether snprintf understands %zu... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5
$as_echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <stdio.h>
int
main ()
{
size_t a = 1, b = 2;
char z[128];
snprintf(z, sizeof z, "%zu%zu", a, b);
exit(strcmp(z, "12"));
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
# We depend on vsnprintf returning the right thing on overflow: the
# number of characters it tried to create (as per SUSv3)
if test "x$ac_cv_func_vsnprintf" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5
$as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working vsnprintf()" >&5
$as_echo "$as_me: WARNING: cross compiling: Assuming working vsnprintf()" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
int x_snprintf(char *str, size_t count, const char *fmt, ...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
return ret;
}
int
main ()
{
char x[1];
if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11)
return 1;
if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11)
return 1;
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&5
$as_echo "$as_me: WARNING: ****** Your vsnprintf() function is broken, complain to your vendor" >&2;}
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
# On systems where [v]snprintf is broken, but is declared in stdio,
# check that the fmt argument is const char * or just char *.
# This is only useful for when BROKEN_SNPRINTF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether snprintf can declare const char *fmt" >&5
$as_echo_n "checking whether snprintf can declare const char *fmt... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int snprintf(char *a, size_t b, const char *c, ...) { return 0; }
int
main ()
{
snprintf(0, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define SNPRINTF_CONST const" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define SNPRINTF_CONST /* not const */" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
# Check for missing getpeereid (or equiv) support
NO_PEERCHECK=""
if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether system supports SO_PEERCRED getsockopt" >&5
$as_echo_n "checking whether system supports SO_PEERCRED getsockopt... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
int i = SO_PEERCRED;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_SO_PEERCRED 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
NO_PEERCHECK=1
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x$ac_cv_func_mkdtemp" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for (overly) strict mkstemp" >&5
$as_echo_n "checking for (overly) strict mkstemp... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_STRICT_MKSTEMP 1" >>confdefs.h
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
int
main ()
{
char template[]="conftest.mkstemp-test";
if (mkstemp(template) == -1)
exit(1);
unlink(template);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_STRICT_MKSTEMP 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
if test ! -z "$check_for_openpty_ctty_bug"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if openpty correctly handles controlling tty" >&5
$as_echo_n "checking if openpty correctly handles controlling tty... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5
$as_echo "cross-compiling, assuming yes" >&6; }
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
int
main ()
{
pid_t pid;
int fd, ptyfd, ttyfd, status;
pid = fork();
if (pid < 0) { /* failed */
exit(1);
} else if (pid > 0) { /* parent */
waitpid(pid, &status, 0);
if (WIFEXITED(status))
exit(WEXITSTATUS(status));
else
exit(2);
} else { /* child */
close(0); close(1); close(2);
setsid();
openpty(&ptyfd, &ttyfd, NULL, NULL, NULL);
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
if (fd >= 0)
exit(3); /* Acquired ctty: broken */
else
exit(0); /* Did not acquire ctty: OK */
}
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define SSHD_ACQUIRES_CTTY 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5
$as_echo_n "checking if getaddrinfo seems to work... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming yes" >&5
$as_echo "cross-compiling, assuming yes" >&6; }
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/in.h>
#define TEST_PORT "2222"
int
main ()
{
int err, sock;
struct addrinfo *gai_ai, *ai, hints;
char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
if (err != 0) {
fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
exit(1);
}
for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family != AF_INET6)
continue;
err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV);
if (err != 0) {
if (err == EAI_SYSTEM)
perror("getnameinfo EAI_SYSTEM");
else
fprintf(stderr, "getnameinfo failed: %s\n",
gai_strerror(err));
exit(2);
}
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0)
perror("socket");
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
if (errno == EBADF)
exit(3);
}
}
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
test "x$check_for_aix_broken_getaddrinfo" = "x1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if getaddrinfo seems to work" >&5
$as_echo_n "checking if getaddrinfo seems to work... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling, assuming no" >&5
$as_echo "cross-compiling, assuming no" >&6; }
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/in.h>
#define TEST_PORT "2222"
int
main ()
{
int err, sock;
struct addrinfo *gai_ai, *ai, hints;
char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
if (err != 0) {
fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
exit(1);
}
for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
continue;
err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV);
if (ai->ai_family == AF_INET && err != 0) {
perror("getnameinfo");
exit(2);
}
}
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define AIX_GETNAMEINFO_HACK 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_GETADDRINFO 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
if test "x$ac_cv_func_getaddrinfo" = "xyes"; then
ac_fn_c_check_decl "$LINENO" "AI_NUMERICSERV" "ac_cv_have_decl_AI_NUMERICSERV" "#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
"
if test "x$ac_cv_have_decl_AI_NUMERICSERV" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_AI_NUMERICSERV $ac_have_decl
_ACEOF
fi
if test "x$check_for_conflicting_getspnam" = "x1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for conflicting getspnam in shadow.h" >&5
$as_echo_n "checking for conflicting getspnam in shadow.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <shadow.h>
int
main ()
{
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define GETSPNAM_CONFLICTING_DEFS 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test "x$ac_cv_func_strnvis" = "xyes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strnvis" >&5
$as_echo_n "checking for working strnvis... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming broken" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming broken" >&2;}
$as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <vis.h>
static void sighandler(int sig) { _exit(1); }
int
main ()
{
char dst[16];
signal(SIGSEGV, sighandler);
if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0)
exit(0);
exit(1)
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
for ac_func in getpgrp
do :
ac_fn_c_check_func "$LINENO" "getpgrp" "ac_cv_func_getpgrp"
if test "x$ac_cv_func_getpgrp" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GETPGRP 1
_ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if getpgrp accepts zero args" >&5
$as_echo_n "checking if getpgrp accepts zero args... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
main ()
{
getpgrp();
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define GETPGRP_VOID 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define GETPGRP_VOID 0" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
done
# Search for OpenSSL
saved_CPPFLAGS="$CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
# Check whether --with-ssl-dir was given.
if test "${with_ssl_dir+set}" = set; then :
withval=$with_ssl_dir;
if test "x$openssl" = "xno" ; then
as_fn_error $? "cannot use --with-ssl-dir when OpenSSL disabled" "$LINENO" 5
fi
if test "x$withval" != "xno" ; then
case "$withval" in
# Relative paths
./*|../*) withval="`pwd`/$withval"
esac
if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
elif test -d "$withval/lib64"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib64 -R${withval}/lib64 ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib64 ${rpath_opt}${withval}/lib64 ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib64 ${LDFLAGS}"
fi
else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}"
else
LDFLAGS="-L${withval} ${LDFLAGS}"
fi
fi
if test -d "$withval/include"; then
CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
else
CPPFLAGS="-I${withval} ${CPPFLAGS}"
fi
fi
fi
# Check whether --with-openssl-header-check was given.
if test "${with_openssl_header_check+set}" = set; then :
withval=$with_openssl_header_check;
if test "x$withval" = "xno" ; then
openssl_check_nonfatal=1
fi
fi
openssl_engine=no
# Check whether --with-ssl-engine was given.
if test "${with_ssl_engine+set}" = set; then :
withval=$with_ssl_engine;
if test "x$withval" != "xno" ; then
if test "x$openssl" = "xno" ; then
as_fn_error $? "cannot use --with-ssl-engine when OpenSSL disabled" "$LINENO" 5
fi
openssl_engine=yes
fi
fi
if test "x$openssl" = "xyes" ; then
LIBS="-lcrypto $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char RAND_add ();
int
main ()
{
return RAND_add ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
-$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
-
else
-
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}"
- else
- LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}"
- fi
- CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}"
- ac_fn_c_check_header_mongrel "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default"
+ as_fn_error $? "*** working libcrypto not found, check config.log" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_fn_c_check_header_mongrel "$LINENO" "openssl/opensslv.h" "ac_cv_header_openssl_opensslv_h" "$ac_includes_default"
if test "x$ac_cv_header_openssl_opensslv_h" = xyes; then :
else
as_fn_error $? "*** OpenSSL headers missing - please install first or check config.log ***" "$LINENO" 5
fi
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RAND_add ();
-int
-main ()
-{
-return RAND_add ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- $as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
-
-else
-
- as_fn_error $? "*** Can't find recent OpenSSL libcrypto (see config.log for details) ***" "$LINENO" 5
-
-
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
-
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
# Determine OpenSSL header version
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL header version" >&5
$as_echo_n "checking OpenSSL header version... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/opensslv.h>
#define DATA "conftest.sslincver"
int
main ()
{
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
if ((rc = fprintf(fd, "%08lx (%s)\n",
(unsigned long)OPENSSL_VERSION_NUMBER,
OPENSSL_VERSION_TEXT)) < 0)
exit(1);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ssl_header_ver=`cat conftest.sslincver`
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_header_ver" >&5
$as_echo "$ssl_header_ver" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
as_fn_error $? "OpenSSL version header not found." "$LINENO" 5
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
+ # Determining OpenSSL library version is version dependent.
+ for ac_func in OpenSSL_version OpenSSL_version_num
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
# Determine OpenSSL library version
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL library version" >&5
$as_echo_n "checking OpenSSL library version... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <string.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#define DATA "conftest.ssllibver"
int
main ()
{
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
-
- if ((rc = fprintf(fd, "%08lx (%s)\n", (unsigned long)SSLeay(),
- SSLeay_version(SSLEAY_VERSION))) < 0)
+#ifndef OPENSSL_VERSION
+# define OPENSSL_VERSION SSLEAY_VERSION
+#endif
+#ifndef HAVE_OPENSSL_VERSION
+# define OpenSSL_version SSLeay_version
+#endif
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
+#endif
+ if ((rc = fprintf(fd, "%08lx (%s)\n",
+ (unsigned long)OpenSSL_version_num(),
+ OpenSSL_version(OPENSSL_VERSION))) < 0)
exit(1);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ssl_library_ver=`cat conftest.ssllibver`
# Check version is supported.
case "$ssl_library_ver" in
10000*|0*)
as_fn_error $? "OpenSSL >= 1.0.1 required (have \"$ssl_library_ver\")" "$LINENO" 5
;;
100*) ;; # 1.0.x
- 1010000123456*)
+ 101000[0123456]*)
# https://github.com/openssl/openssl/pull/4613
as_fn_error $? "OpenSSL 1.1.x versions prior to 1.1.0g have a bug that breaks their use with OpenSSH (have \"$ssl_library_ver\")" "$LINENO" 5
;;
101*) ;; # 1.1.x
200*) ;; # LibreSSL
+ 300*) ;; # OpenSSL development branch.
*)
- as_fn_error $? "OpenSSL > 1.1.x is not yet supported (have \"$ssl_library_ver\")" "$LINENO" 5
+ as_fn_error $? "Unknown/unsupported OpenSSL version (\"$ssl_library_ver\")" "$LINENO" 5
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5
$as_echo "$ssl_library_ver" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
as_fn_error $? "OpenSSL library not found." "$LINENO" 5
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
# Sanity check OpenSSL headers
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's headers match the library" >&5
$as_echo_n "checking whether OpenSSL's headers match the library... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
int
main ()
{
- exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1);
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
+#endif
+ exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if test "x$openssl_check_nonfatal" = "x"; then
as_fn_error $? "Your OpenSSL headers do not match your
library. Check config.log for details.
If you are sure your installation is consistent, you can disable the check
by running \"./configure --without-openssl-header-check\".
Also see contrib/findssl.sh for help identifying header/library mismatches.
" "$LINENO" 5
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Your OpenSSL headers do not match your
library. Check config.log for details.
Also see contrib/findssl.sh for help identifying header/library mismatches." >&5
$as_echo "$as_me: WARNING: Your OpenSSL headers do not match your
library. Check config.log for details.
Also see contrib/findssl.sh for help identifying header/library mismatches." >&2;}
fi
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL functions will link" >&5
$as_echo_n "checking if programs using OpenSSL functions will link... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
- #include <openssl/evp.h>
+ #include <openssl/err.h>
int
main ()
{
- SSLeay_add_all_algorithms();
+ ERR_load_crypto_strings();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
saved_LIBS="$LIBS"
LIBS="$LIBS -ldl"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if programs using OpenSSL need -ldl" >&5
$as_echo_n "checking if programs using OpenSSL need -ldl... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
- #include <openssl/evp.h>
+ #include <openssl/err.h>
int
main ()
{
- SSLeay_add_all_algorithms();
+ ERR_load_crypto_strings();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
LIBS="$saved_LIBS"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
for ac_func in \
BN_is_prime_ex \
DSA_generate_parameters_ex \
- EVP_DigestInit_ex \
+ EVP_CIPHER_CTX_ctrl \
EVP_DigestFinal_ex \
- EVP_MD_CTX_init \
+ EVP_DigestInit_ex \
EVP_MD_CTX_cleanup \
EVP_MD_CTX_copy_ex \
+ EVP_MD_CTX_init \
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
+fi
+done
+
+
+ # OpenSSL_add_all_algorithms may be a macro.
+ ac_fn_c_check_func "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_func_OpenSSL_add_all_algorithms"
+if test "x$ac_cv_func_OpenSSL_add_all_algorithms" = xyes; then :
+
+$as_echo "#define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1" >>confdefs.h
+
+else
+ ac_fn_c_check_decl "$LINENO" "OpenSSL_add_all_algorithms" "ac_cv_have_decl_OpenSSL_add_all_algorithms" "#include <openssl/evp.h>
+
+"
+if test "x$ac_cv_have_decl_OpenSSL_add_all_algorithms" = xyes; then :
+
+$as_echo "#define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1" >>confdefs.h
+
+fi
+
+
+fi
+
+
+ # LibreSSL/OpenSSL 1.1x API
+ for ac_func in \
+ OPENSSL_init_crypto \
+ DH_get0_key \
+ DH_get0_pqg \
+ DH_set0_key \
+ DH_set_length \
+ DH_set0_pqg \
+ DSA_get0_key \
+ DSA_get0_pqg \
+ DSA_set0_key \
+ DSA_set0_pqg \
+ DSA_SIG_get0 \
+ DSA_SIG_set0 \
+ ECDSA_SIG_get0 \
+ ECDSA_SIG_set0 \
+ EVP_CIPHER_CTX_iv \
+ EVP_CIPHER_CTX_iv_noconst \
+ EVP_CIPHER_CTX_get_iv \
+ EVP_CIPHER_CTX_set_iv \
+ RSA_get0_crt_params \
+ RSA_get0_factors \
+ RSA_get0_key \
+ RSA_set0_crt_params \
+ RSA_set0_factors \
+ RSA_set0_key \
+ RSA_meth_free \
+ RSA_meth_dup \
+ RSA_meth_set1_name \
+ RSA_meth_get_finish \
+ RSA_meth_set_priv_enc \
+ RSA_meth_set_priv_dec \
+ RSA_meth_set_finish \
+ EVP_PKEY_get0_RSA \
+ EVP_MD_CTX_new \
+ EVP_MD_CTX_free \
+
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
fi
done
if test "x$openssl_engine" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL ENGINE support" >&5
$as_echo_n "checking for OpenSSL ENGINE support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/engine.h>
int
main ()
{
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define USE_OPENSSL_ENGINE 1" >>confdefs.h
else
as_fn_error $? "OpenSSL ENGINE support not found" "$LINENO" 5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
# Check for OpenSSL without EVP_aes_{192,256}_cbc
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has crippled AES support" >&5
$as_echo_n "checking whether OpenSSL has crippled AES support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
#include <openssl/evp.h>
int
main ()
{
exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define OPENSSL_LOBOTOMISED_AES 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
# Check for OpenSSL with EVP_aes_*ctr
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has AES CTR via EVP" >&5
$as_echo_n "checking whether OpenSSL has AES CTR via EVP... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
#include <openssl/evp.h>
int
main ()
{
exit(EVP_aes_128_ctr() == NULL ||
EVP_aes_192_cbc() == NULL ||
EVP_aes_256_cbc() == NULL);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define OPENSSL_HAVE_EVPCTR 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
# Check for OpenSSL with EVP_aes_*gcm
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has AES GCM via EVP" >&5
$as_echo_n "checking whether OpenSSL has AES GCM via EVP... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
#include <openssl/evp.h>
int
main ()
{
exit(EVP_aes_128_gcm() == NULL ||
EVP_aes_256_gcm() == NULL ||
EVP_CTRL_GCM_SET_IV_FIXED == 0 ||
EVP_CTRL_GCM_IV_GEN == 0 ||
EVP_CTRL_GCM_SET_TAG == 0 ||
EVP_CTRL_GCM_GET_TAG == 0 ||
EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define OPENSSL_HAVE_EVPGCM 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
unsupported_algorithms="$unsupported_cipers \
aes128-gcm@openssh.com \
aes256-gcm@openssh.com"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_CIPHER_CTX_ctrl" >&5
-$as_echo_n "checking for library containing EVP_CIPHER_CTX_ctrl... " >&6; }
-if ${ac_cv_search_EVP_CIPHER_CTX_ctrl+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_CIPHER_CTX_ctrl ();
-int
-main ()
-{
-return EVP_CIPHER_CTX_ctrl ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_CIPHER_CTX_ctrl=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_CIPHER_CTX_ctrl+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_CIPHER_CTX_ctrl+:} false; then :
-
-else
- ac_cv_search_EVP_CIPHER_CTX_ctrl=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_CIPHER_CTX_ctrl" >&5
-$as_echo "$ac_cv_search_EVP_CIPHER_CTX_ctrl" >&6; }
-ac_res=$ac_cv_search_EVP_CIPHER_CTX_ctrl
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_CIPHER_CTX_CTRL 1" >>confdefs.h
-
-fi
-
-
- # LibreSSL/OpenSSL 1.1x API
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DH_get0_key" >&5
-$as_echo_n "checking for library containing DH_get0_key... " >&6; }
-if ${ac_cv_search_DH_get0_key+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DH_get0_key ();
-int
-main ()
-{
-return DH_get0_key ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DH_get0_key=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DH_get0_key+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DH_get0_key+:} false; then :
-
-else
- ac_cv_search_DH_get0_key=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DH_get0_key" >&5
-$as_echo "$ac_cv_search_DH_get0_key" >&6; }
-ac_res=$ac_cv_search_DH_get0_key
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DH_GET0_KEY 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DH_get0_pqg" >&5
-$as_echo_n "checking for library containing DH_get0_pqg... " >&6; }
-if ${ac_cv_search_DH_get0_pqg+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DH_get0_pqg ();
-int
-main ()
-{
-return DH_get0_pqg ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DH_get0_pqg=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DH_get0_pqg+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DH_get0_pqg+:} false; then :
-
-else
- ac_cv_search_DH_get0_pqg=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DH_get0_pqg" >&5
-$as_echo "$ac_cv_search_DH_get0_pqg" >&6; }
-ac_res=$ac_cv_search_DH_get0_pqg
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DH_GET0_PQG 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DH_set0_key" >&5
-$as_echo_n "checking for library containing DH_set0_key... " >&6; }
-if ${ac_cv_search_DH_set0_key+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DH_set0_key ();
-int
-main ()
-{
-return DH_set0_key ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DH_set0_key=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DH_set0_key+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DH_set0_key+:} false; then :
-
-else
- ac_cv_search_DH_set0_key=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DH_set0_key" >&5
-$as_echo "$ac_cv_search_DH_set0_key" >&6; }
-ac_res=$ac_cv_search_DH_set0_key
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DH_SET0_KEY 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DH_set_length" >&5
-$as_echo_n "checking for library containing DH_set_length... " >&6; }
-if ${ac_cv_search_DH_set_length+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DH_set_length ();
-int
-main ()
-{
-return DH_set_length ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DH_set_length=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DH_set_length+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DH_set_length+:} false; then :
-
-else
- ac_cv_search_DH_set_length=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DH_set_length" >&5
-$as_echo "$ac_cv_search_DH_set_length" >&6; }
-ac_res=$ac_cv_search_DH_set_length
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DH_SET_LENGTH 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DH_set0_pqg" >&5
-$as_echo_n "checking for library containing DH_set0_pqg... " >&6; }
-if ${ac_cv_search_DH_set0_pqg+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DH_set0_pqg ();
-int
-main ()
-{
-return DH_set0_pqg ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DH_set0_pqg=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DH_set0_pqg+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DH_set0_pqg+:} false; then :
-
-else
- ac_cv_search_DH_set0_pqg=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DH_set0_pqg" >&5
-$as_echo "$ac_cv_search_DH_set0_pqg" >&6; }
-ac_res=$ac_cv_search_DH_set0_pqg
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DH_SET0_PQG 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DSA_get0_key" >&5
-$as_echo_n "checking for library containing DSA_get0_key... " >&6; }
-if ${ac_cv_search_DSA_get0_key+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DSA_get0_key ();
-int
-main ()
-{
-return DSA_get0_key ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DSA_get0_key=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DSA_get0_key+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DSA_get0_key+:} false; then :
-
-else
- ac_cv_search_DSA_get0_key=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DSA_get0_key" >&5
-$as_echo "$ac_cv_search_DSA_get0_key" >&6; }
-ac_res=$ac_cv_search_DSA_get0_key
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DSA_GET0_KEY 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DSA_get0_pqg" >&5
-$as_echo_n "checking for library containing DSA_get0_pqg... " >&6; }
-if ${ac_cv_search_DSA_get0_pqg+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DSA_get0_pqg ();
-int
-main ()
-{
-return DSA_get0_pqg ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DSA_get0_pqg=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DSA_get0_pqg+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DSA_get0_pqg+:} false; then :
-
-else
- ac_cv_search_DSA_get0_pqg=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DSA_get0_pqg" >&5
-$as_echo "$ac_cv_search_DSA_get0_pqg" >&6; }
-ac_res=$ac_cv_search_DSA_get0_pqg
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DSA_GET0_PQG 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DSA_set0_key" >&5
-$as_echo_n "checking for library containing DSA_set0_key... " >&6; }
-if ${ac_cv_search_DSA_set0_key+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DSA_set0_key ();
-int
-main ()
-{
-return DSA_set0_key ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DSA_set0_key=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DSA_set0_key+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DSA_set0_key+:} false; then :
-
-else
- ac_cv_search_DSA_set0_key=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DSA_set0_key" >&5
-$as_echo "$ac_cv_search_DSA_set0_key" >&6; }
-ac_res=$ac_cv_search_DSA_set0_key
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DSA_SET0_KEY 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DSA_set0_pqg" >&5
-$as_echo_n "checking for library containing DSA_set0_pqg... " >&6; }
-if ${ac_cv_search_DSA_set0_pqg+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DSA_set0_pqg ();
-int
-main ()
-{
-return DSA_set0_pqg ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DSA_set0_pqg=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DSA_set0_pqg+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DSA_set0_pqg+:} false; then :
-
-else
- ac_cv_search_DSA_set0_pqg=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DSA_set0_pqg" >&5
-$as_echo "$ac_cv_search_DSA_set0_pqg" >&6; }
-ac_res=$ac_cv_search_DSA_set0_pqg
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DSA_SET0_PQG 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DSA_SIG_get0" >&5
-$as_echo_n "checking for library containing DSA_SIG_get0... " >&6; }
-if ${ac_cv_search_DSA_SIG_get0+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DSA_SIG_get0 ();
-int
-main ()
-{
-return DSA_SIG_get0 ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DSA_SIG_get0=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DSA_SIG_get0+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DSA_SIG_get0+:} false; then :
-
-else
- ac_cv_search_DSA_SIG_get0=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DSA_SIG_get0" >&5
-$as_echo "$ac_cv_search_DSA_SIG_get0" >&6; }
-ac_res=$ac_cv_search_DSA_SIG_get0
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DSA_SIG_GET0 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing DSA_SIG_set0" >&5
-$as_echo_n "checking for library containing DSA_SIG_set0... " >&6; }
-if ${ac_cv_search_DSA_SIG_set0+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DSA_SIG_set0 ();
-int
-main ()
-{
-return DSA_SIG_set0 ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_DSA_SIG_set0=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_DSA_SIG_set0+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_DSA_SIG_set0+:} false; then :
-
-else
- ac_cv_search_DSA_SIG_set0=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_DSA_SIG_set0" >&5
-$as_echo "$ac_cv_search_DSA_SIG_set0" >&6; }
-ac_res=$ac_cv_search_DSA_SIG_set0
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_DSA_SIG_SET0 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ECDSA_SIG_get0" >&5
-$as_echo_n "checking for library containing ECDSA_SIG_get0... " >&6; }
-if ${ac_cv_search_ECDSA_SIG_get0+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ECDSA_SIG_get0 ();
-int
-main ()
-{
-return ECDSA_SIG_get0 ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_ECDSA_SIG_get0=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_ECDSA_SIG_get0+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_ECDSA_SIG_get0+:} false; then :
-
-else
- ac_cv_search_ECDSA_SIG_get0=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ECDSA_SIG_get0" >&5
-$as_echo "$ac_cv_search_ECDSA_SIG_get0" >&6; }
-ac_res=$ac_cv_search_ECDSA_SIG_get0
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_ECDSA_SIG_GET0 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ECDSA_SIG_set0" >&5
-$as_echo_n "checking for library containing ECDSA_SIG_set0... " >&6; }
-if ${ac_cv_search_ECDSA_SIG_set0+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ECDSA_SIG_set0 ();
-int
-main ()
-{
-return ECDSA_SIG_set0 ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_ECDSA_SIG_set0=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_ECDSA_SIG_set0+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_ECDSA_SIG_set0+:} false; then :
-
-else
- ac_cv_search_ECDSA_SIG_set0=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ECDSA_SIG_set0" >&5
-$as_echo "$ac_cv_search_ECDSA_SIG_set0" >&6; }
-ac_res=$ac_cv_search_ECDSA_SIG_set0
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_ECDSA_SIG_SET0 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_CIPHER_CTX_iv" >&5
-$as_echo_n "checking for library containing EVP_CIPHER_CTX_iv... " >&6; }
-if ${ac_cv_search_EVP_CIPHER_CTX_iv+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_CIPHER_CTX_iv ();
-int
-main ()
-{
-return EVP_CIPHER_CTX_iv ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_CIPHER_CTX_iv=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_CIPHER_CTX_iv+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_CIPHER_CTX_iv+:} false; then :
-
-else
- ac_cv_search_EVP_CIPHER_CTX_iv=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_CIPHER_CTX_iv" >&5
-$as_echo "$ac_cv_search_EVP_CIPHER_CTX_iv" >&6; }
-ac_res=$ac_cv_search_EVP_CIPHER_CTX_iv
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_CIPHER_CTX_IV 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_CIPHER_CTX_iv_noconst" >&5
-$as_echo_n "checking for library containing EVP_CIPHER_CTX_iv_noconst... " >&6; }
-if ${ac_cv_search_EVP_CIPHER_CTX_iv_noconst+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_CIPHER_CTX_iv_noconst ();
-int
-main ()
-{
-return EVP_CIPHER_CTX_iv_noconst ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_CIPHER_CTX_iv_noconst=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_CIPHER_CTX_iv_noconst+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_CIPHER_CTX_iv_noconst+:} false; then :
-
-else
- ac_cv_search_EVP_CIPHER_CTX_iv_noconst=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_CIPHER_CTX_iv_noconst" >&5
-$as_echo "$ac_cv_search_EVP_CIPHER_CTX_iv_noconst" >&6; }
-ac_res=$ac_cv_search_EVP_CIPHER_CTX_iv_noconst
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_CIPHER_CTX_IV_NOCONST 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_CIPHER_CTX_get_iv" >&5
-$as_echo_n "checking for library containing EVP_CIPHER_CTX_get_iv... " >&6; }
-if ${ac_cv_search_EVP_CIPHER_CTX_get_iv+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_CIPHER_CTX_get_iv ();
-int
-main ()
-{
-return EVP_CIPHER_CTX_get_iv ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_CIPHER_CTX_get_iv=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_CIPHER_CTX_get_iv+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_CIPHER_CTX_get_iv+:} false; then :
-
-else
- ac_cv_search_EVP_CIPHER_CTX_get_iv=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_CIPHER_CTX_get_iv" >&5
-$as_echo "$ac_cv_search_EVP_CIPHER_CTX_get_iv" >&6; }
-ac_res=$ac_cv_search_EVP_CIPHER_CTX_get_iv
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_CIPHER_CTX_GET_IV 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_CIPHER_CTX_set_iv" >&5
-$as_echo_n "checking for library containing EVP_CIPHER_CTX_set_iv... " >&6; }
-if ${ac_cv_search_EVP_CIPHER_CTX_set_iv+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_CIPHER_CTX_set_iv ();
-int
-main ()
-{
-return EVP_CIPHER_CTX_set_iv ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_CIPHER_CTX_set_iv=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_CIPHER_CTX_set_iv+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_CIPHER_CTX_set_iv+:} false; then :
-
-else
- ac_cv_search_EVP_CIPHER_CTX_set_iv=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_CIPHER_CTX_set_iv" >&5
-$as_echo "$ac_cv_search_EVP_CIPHER_CTX_set_iv" >&6; }
-ac_res=$ac_cv_search_EVP_CIPHER_CTX_set_iv
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_CIPHER_CTX_GET_IV 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_get0_crt_params" >&5
-$as_echo_n "checking for library containing RSA_get0_crt_params... " >&6; }
-if ${ac_cv_search_RSA_get0_crt_params+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_get0_crt_params ();
-int
-main ()
-{
-return RSA_get0_crt_params ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_get0_crt_params=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_get0_crt_params+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_get0_crt_params+:} false; then :
-
-else
- ac_cv_search_RSA_get0_crt_params=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_get0_crt_params" >&5
-$as_echo "$ac_cv_search_RSA_get0_crt_params" >&6; }
-ac_res=$ac_cv_search_RSA_get0_crt_params
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_GET0_CRT_PARAMS 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_get0_factors" >&5
-$as_echo_n "checking for library containing RSA_get0_factors... " >&6; }
-if ${ac_cv_search_RSA_get0_factors+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_get0_factors ();
-int
-main ()
-{
-return RSA_get0_factors ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_get0_factors=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_get0_factors+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_get0_factors+:} false; then :
-
-else
- ac_cv_search_RSA_get0_factors=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_get0_factors" >&5
-$as_echo "$ac_cv_search_RSA_get0_factors" >&6; }
-ac_res=$ac_cv_search_RSA_get0_factors
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_GET0_FACTORS 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_get0_key" >&5
-$as_echo_n "checking for library containing RSA_get0_key... " >&6; }
-if ${ac_cv_search_RSA_get0_key+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_get0_key ();
-int
-main ()
-{
-return RSA_get0_key ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_get0_key=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_get0_key+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_get0_key+:} false; then :
-
-else
- ac_cv_search_RSA_get0_key=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_get0_key" >&5
-$as_echo "$ac_cv_search_RSA_get0_key" >&6; }
-ac_res=$ac_cv_search_RSA_get0_key
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_GET0_KEY 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_set0_crt_params" >&5
-$as_echo_n "checking for library containing RSA_set0_crt_params... " >&6; }
-if ${ac_cv_search_RSA_set0_crt_params+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_set0_crt_params ();
-int
-main ()
-{
-return RSA_set0_crt_params ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_set0_crt_params=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_set0_crt_params+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_set0_crt_params+:} false; then :
-
-else
- ac_cv_search_RSA_set0_crt_params=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_set0_crt_params" >&5
-$as_echo "$ac_cv_search_RSA_set0_crt_params" >&6; }
-ac_res=$ac_cv_search_RSA_set0_crt_params
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_SET0_CRT_PARAMS 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_set0_factors" >&5
-$as_echo_n "checking for library containing RSA_set0_factors... " >&6; }
-if ${ac_cv_search_RSA_set0_factors+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_set0_factors ();
-int
-main ()
-{
-return RSA_set0_factors ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_set0_factors=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_set0_factors+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_set0_factors+:} false; then :
-
-else
- ac_cv_search_RSA_set0_factors=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_set0_factors" >&5
-$as_echo "$ac_cv_search_RSA_set0_factors" >&6; }
-ac_res=$ac_cv_search_RSA_set0_factors
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_SET0_FACTORS 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_set0_key" >&5
-$as_echo_n "checking for library containing RSA_set0_key... " >&6; }
-if ${ac_cv_search_RSA_set0_key+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_set0_key ();
-int
-main ()
-{
-return RSA_set0_key ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_set0_key=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_set0_key+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_set0_key+:} false; then :
-
-else
- ac_cv_search_RSA_set0_key=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_set0_key" >&5
-$as_echo "$ac_cv_search_RSA_set0_key" >&6; }
-ac_res=$ac_cv_search_RSA_set0_key
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_SET0_KEY 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_free" >&5
-$as_echo_n "checking for library containing RSA_meth_free... " >&6; }
-if ${ac_cv_search_RSA_meth_free+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_free ();
-int
-main ()
-{
-return RSA_meth_free ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_free=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_free+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_free+:} false; then :
-
-else
- ac_cv_search_RSA_meth_free=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_free" >&5
-$as_echo "$ac_cv_search_RSA_meth_free" >&6; }
-ac_res=$ac_cv_search_RSA_meth_free
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_FREE 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_dup" >&5
-$as_echo_n "checking for library containing RSA_meth_dup... " >&6; }
-if ${ac_cv_search_RSA_meth_dup+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_dup ();
-int
-main ()
-{
-return RSA_meth_dup ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_dup=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_dup+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_dup+:} false; then :
-
-else
- ac_cv_search_RSA_meth_dup=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_dup" >&5
-$as_echo "$ac_cv_search_RSA_meth_dup" >&6; }
-ac_res=$ac_cv_search_RSA_meth_dup
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_DUP 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_set1_name" >&5
-$as_echo_n "checking for library containing RSA_meth_set1_name... " >&6; }
-if ${ac_cv_search_RSA_meth_set1_name+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_set1_name ();
-int
-main ()
-{
-return RSA_meth_set1_name ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_set1_name=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_set1_name+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_set1_name+:} false; then :
-
-else
- ac_cv_search_RSA_meth_set1_name=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_set1_name" >&5
-$as_echo "$ac_cv_search_RSA_meth_set1_name" >&6; }
-ac_res=$ac_cv_search_RSA_meth_set1_name
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_SET1_NAME 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_get_finish" >&5
-$as_echo_n "checking for library containing RSA_meth_get_finish... " >&6; }
-if ${ac_cv_search_RSA_meth_get_finish+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_get_finish ();
-int
-main ()
-{
-return RSA_meth_get_finish ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_get_finish=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_get_finish+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_get_finish+:} false; then :
-
-else
- ac_cv_search_RSA_meth_get_finish=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_get_finish" >&5
-$as_echo "$ac_cv_search_RSA_meth_get_finish" >&6; }
-ac_res=$ac_cv_search_RSA_meth_get_finish
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_GET_FINISH 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_set_priv_enc" >&5
-$as_echo_n "checking for library containing RSA_meth_set_priv_enc... " >&6; }
-if ${ac_cv_search_RSA_meth_set_priv_enc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_set_priv_enc ();
-int
-main ()
-{
-return RSA_meth_set_priv_enc ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_set_priv_enc=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_set_priv_enc+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_set_priv_enc+:} false; then :
-
-else
- ac_cv_search_RSA_meth_set_priv_enc=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_set_priv_enc" >&5
-$as_echo "$ac_cv_search_RSA_meth_set_priv_enc" >&6; }
-ac_res=$ac_cv_search_RSA_meth_set_priv_enc
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_SET_PRIV_ENC 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_set_priv_dec" >&5
-$as_echo_n "checking for library containing RSA_meth_set_priv_dec... " >&6; }
-if ${ac_cv_search_RSA_meth_set_priv_dec+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_set_priv_dec ();
-int
-main ()
-{
-return RSA_meth_set_priv_dec ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_set_priv_dec=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_set_priv_dec+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_set_priv_dec+:} false; then :
-
-else
- ac_cv_search_RSA_meth_set_priv_dec=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_set_priv_dec" >&5
-$as_echo "$ac_cv_search_RSA_meth_set_priv_dec" >&6; }
-ac_res=$ac_cv_search_RSA_meth_set_priv_dec
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_SET_PRIV_DEC 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RSA_meth_set_finish" >&5
-$as_echo_n "checking for library containing RSA_meth_set_finish... " >&6; }
-if ${ac_cv_search_RSA_meth_set_finish+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char RSA_meth_set_finish ();
-int
-main ()
-{
-return RSA_meth_set_finish ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_RSA_meth_set_finish=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_RSA_meth_set_finish+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_RSA_meth_set_finish+:} false; then :
-
-else
- ac_cv_search_RSA_meth_set_finish=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RSA_meth_set_finish" >&5
-$as_echo "$ac_cv_search_RSA_meth_set_finish" >&6; }
-ac_res=$ac_cv_search_RSA_meth_set_finish
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_RSA_METH_SET_FINISH 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_PKEY_get0_RSA" >&5
-$as_echo_n "checking for library containing EVP_PKEY_get0_RSA... " >&6; }
-if ${ac_cv_search_EVP_PKEY_get0_RSA+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_PKEY_get0_RSA ();
-int
-main ()
-{
-return EVP_PKEY_get0_RSA ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_PKEY_get0_RSA=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_PKEY_get0_RSA+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_PKEY_get0_RSA+:} false; then :
-
-else
- ac_cv_search_EVP_PKEY_get0_RSA=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_PKEY_get0_RSA" >&5
-$as_echo "$ac_cv_search_EVP_PKEY_get0_RSA" >&6; }
-ac_res=$ac_cv_search_EVP_PKEY_get0_RSA
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_PKEY_GET0_RSA 1" >>confdefs.h
-
-fi
-
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_MD_CTX_new" >&5
-$as_echo_n "checking for library containing EVP_MD_CTX_new... " >&6; }
-if ${ac_cv_search_EVP_MD_CTX_new+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_MD_CTX_new ();
-int
-main ()
-{
-return EVP_MD_CTX_new ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_MD_CTX_new=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_MD_CTX_new+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_MD_CTX_new+:} false; then :
-
-else
- ac_cv_search_EVP_MD_CTX_new=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_MD_CTX_new" >&5
-$as_echo "$ac_cv_search_EVP_MD_CTX_new" >&6; }
-ac_res=$ac_cv_search_EVP_MD_CTX_new
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_MD_CTX_NEW 1" >>confdefs.h
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing EVP_MD_CTX_free" >&5
-$as_echo_n "checking for library containing EVP_MD_CTX_free... " >&6; }
-if ${ac_cv_search_EVP_MD_CTX_free+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char EVP_MD_CTX_free ();
-int
-main ()
-{
-return EVP_MD_CTX_free ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' crypto; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_EVP_MD_CTX_free=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_EVP_MD_CTX_free+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_EVP_MD_CTX_free+:} false; then :
-
-else
- ac_cv_search_EVP_MD_CTX_free=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_EVP_MD_CTX_free" >&5
-$as_echo "$ac_cv_search_EVP_MD_CTX_free" >&6; }
-ac_res=$ac_cv_search_EVP_MD_CTX_free
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-$as_echo "#define HAVE_EVP_MD_CTX_FREE 1" >>confdefs.h
-
-fi
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if EVP_DigestUpdate returns an int" >&5
$as_echo_n "checking if EVP_DigestUpdate returns an int... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
#include <openssl/evp.h>
int
main ()
{
if(EVP_DigestUpdate(NULL, NULL,0))
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define OPENSSL_EVP_DIGESTUPDATE_VOID 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
# Some systems want crypt() from libcrypt, *not* the version in OpenSSL,
# because the system crypt() is more featureful.
if test "x$check_for_libcrypt_before" = "x1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
$as_echo_n "checking for crypt in -lcrypt... " >&6; }
if ${ac_cv_lib_crypt_crypt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcrypt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char crypt ();
int
main ()
{
return crypt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_crypt_crypt=yes
else
ac_cv_lib_crypt_crypt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBCRYPT 1
_ACEOF
LIBS="-lcrypt $LIBS"
fi
fi
# Some Linux systems (Slackware) need crypt() from libcrypt, *not* the
# version in OpenSSL.
if test "x$check_for_libcrypt_later" = "x1"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
$as_echo_n "checking for crypt in -lcrypt... " >&6; }
if ${ac_cv_lib_crypt_crypt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcrypt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char crypt ();
int
main ()
{
return crypt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_crypt_crypt=yes
else
ac_cv_lib_crypt_crypt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
LIBS="$LIBS -lcrypt"
fi
fi
for ac_func in crypt DES_crypt
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
# Search for SHA256 support in libc and/or OpenSSL
for ac_func in SHA256_Update EVP_sha256
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
else
unsupported_algorithms="$unsupported_algorithms \
hmac-sha2-256 \
hmac-sha2-512 \
diffie-hellman-group-exchange-sha256 \
hmac-sha2-256-etm@openssh.com \
hmac-sha2-512-etm@openssh.com"
fi
done
# Search for RIPE-MD support in OpenSSL
for ac_func in EVP_ripemd160
do :
ac_fn_c_check_func "$LINENO" "EVP_ripemd160" "ac_cv_func_EVP_ripemd160"
if test "x$ac_cv_func_EVP_ripemd160" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_EVP_RIPEMD160 1
_ACEOF
else
unsupported_algorithms="$unsupported_algorithms \
hmac-ripemd160 \
hmac-ripemd160@openssh.com \
hmac-ripemd160-etm@openssh.com"
fi
done
# Check complete ECC support in OpenSSL
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5
$as_echo_n "checking whether OpenSSL has NID_X9_62_prime256v1... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
int
main ()
{
EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
const EVP_MD *m = EVP_sha256(); /* We need this too */
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
enable_nistp256=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp384r1" >&5
$as_echo_n "checking whether OpenSSL has NID_secp384r1... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
int
main ()
{
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1);
const EVP_MD *m = EVP_sha384(); /* We need this too */
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
enable_nistp384=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_secp521r1" >&5
$as_echo_n "checking whether OpenSSL has NID_secp521r1... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
int
main ()
{
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
const EVP_MD *m = EVP_sha512(); /* We need this too */
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if OpenSSL's NID_secp521r1 is functional" >&5
$as_echo_n "checking if OpenSSL's NID_secp521r1 is functional... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross-compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross-compiling: assuming yes" >&2;}
enable_nistp521=1
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
int
main ()
{
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
const EVP_MD *m = EVP_sha512(); /* We need this too */
exit(e == NULL || m == NULL);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
enable_nistp521=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
COMMENT_OUT_ECC="#no ecc#"
TEST_SSH_ECC=no
if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \
test x$enable_nistp521 = x1; then
$as_echo "#define OPENSSL_HAS_ECC 1" >>confdefs.h
+ for ac_func in EC_KEY_METHOD_new
+do :
+ ac_fn_c_check_func "$LINENO" "EC_KEY_METHOD_new" "ac_cv_func_EC_KEY_METHOD_new"
+if test "x$ac_cv_func_EC_KEY_METHOD_new" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EC_KEY_METHOD_NEW 1
+_ACEOF
+
+fi
+done
+
fi
if test x$enable_nistp256 = x1; then
$as_echo "#define OPENSSL_HAS_NISTP256 1" >>confdefs.h
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdsa-sha2-nistp256 \
ecdh-sha2-nistp256 \
ecdsa-sha2-nistp256-cert-v01@openssh.com"
fi
if test x$enable_nistp384 = x1; then
$as_echo "#define OPENSSL_HAS_NISTP384 1" >>confdefs.h
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdsa-sha2-nistp384 \
ecdh-sha2-nistp384 \
ecdsa-sha2-nistp384-cert-v01@openssh.com"
fi
if test x$enable_nistp521 = x1; then
$as_echo "#define OPENSSL_HAS_NISTP521 1" >>confdefs.h
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdh-sha2-nistp521 \
ecdsa-sha2-nistp521 \
ecdsa-sha2-nistp521-cert-v01@openssh.com"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
$as_echo_n "checking for crypt in -lcrypt... " >&6; }
if ${ac_cv_lib_crypt_crypt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcrypt $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char crypt ();
int
main ()
{
return crypt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_crypt_crypt=yes
else
ac_cv_lib_crypt_crypt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
LIBS="$LIBS -lcrypt"
fi
for ac_func in crypt
do :
ac_fn_c_check_func "$LINENO" "crypt" "ac_cv_func_crypt"
if test "x$ac_cv_func_crypt" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_CRYPT 1
_ACEOF
fi
done
fi
for ac_func in \
arc4random \
arc4random_buf \
arc4random_stir \
arc4random_uniform \
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
saved_LIBS="$LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5
$as_echo_n "checking for ia_openinfo in -liaf... " >&6; }
if ${ac_cv_lib_iaf_ia_openinfo+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-liaf $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char ia_openinfo ();
int
main ()
{
return ia_openinfo ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_iaf_ia_openinfo=yes
else
ac_cv_lib_iaf_ia_openinfo=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iaf_ia_openinfo" >&5
$as_echo "$ac_cv_lib_iaf_ia_openinfo" >&6; }
if test "x$ac_cv_lib_iaf_ia_openinfo" = xyes; then :
LIBS="$LIBS -liaf"
for ac_func in set_id
do :
ac_fn_c_check_func "$LINENO" "set_id" "ac_cv_func_set_id"
if test "x$ac_cv_func_set_id" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SET_ID 1
_ACEOF
SSHDLIBS="$SSHDLIBS -liaf"
$as_echo "#define HAVE_LIBIAF 1" >>confdefs.h
fi
done
fi
LIBS="$saved_LIBS"
### Configure cryptographic random number support
# Check whether OpenSSL seeds itself
if test "x$openssl" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL's PRNG is internally seeded" >&5
$as_echo_n "checking whether OpenSSL's PRNG is internally seeded... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
# This is safe, since we will fatal() at runtime if
# OpenSSL is not seeded correctly.
OPENSSL_SEEDS_ITSELF=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
#include <openssl/rand.h>
int
main ()
{
exit(RAND_status() == 1 ? 0 : 1);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
OPENSSL_SEEDS_ITSELF=yes
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
# PRNGD TCP socket
# Check whether --with-prngd-port was given.
if test "${with_prngd_port+set}" = set; then :
withval=$with_prngd_port;
case "$withval" in
no)
withval=""
;;
[0-9]*)
;;
*)
as_fn_error $? "You must specify a numeric port number for --with-prngd-port" "$LINENO" 5
;;
esac
if test ! -z "$withval" ; then
PRNGD_PORT="$withval"
cat >>confdefs.h <<_ACEOF
#define PRNGD_PORT $PRNGD_PORT
_ACEOF
fi
fi
# PRNGD Unix domain socket
# Check whether --with-prngd-socket was given.
if test "${with_prngd_socket+set}" = set; then :
withval=$with_prngd_socket;
case "$withval" in
yes)
withval="/var/run/egd-pool"
;;
no)
withval=""
;;
/*)
;;
*)
as_fn_error $? "You must specify an absolute path to the entropy socket" "$LINENO" 5
;;
esac
if test ! -z "$withval" ; then
if test ! -z "$PRNGD_PORT" ; then
as_fn_error $? "You may not specify both a PRNGD/EGD port and socket" "$LINENO" 5
fi
if test ! -r "$withval" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Entropy socket is not readable" >&5
$as_echo "$as_me: WARNING: Entropy socket is not readable" >&2;}
fi
PRNGD_SOCKET="$withval"
cat >>confdefs.h <<_ACEOF
#define PRNGD_SOCKET "$PRNGD_SOCKET"
_ACEOF
fi
else
# Check for existing socket only if we don't have a random device already
if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PRNGD/EGD socket" >&5
$as_echo_n "checking for PRNGD/EGD socket... " >&6; }
# Insert other locations here
for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do
if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then
PRNGD_SOCKET="$sock"
cat >>confdefs.h <<_ACEOF
#define PRNGD_SOCKET "$PRNGD_SOCKET"
_ACEOF
break;
fi
done
if test ! -z "$PRNGD_SOCKET" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PRNGD_SOCKET" >&5
$as_echo "$PRNGD_SOCKET" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
fi
fi
fi
# Which randomness source do we use?
if test ! -z "$PRNGD_PORT" ; then
RAND_MSG="PRNGd port $PRNGD_PORT"
elif test ! -z "$PRNGD_SOCKET" ; then
RAND_MSG="PRNGd socket $PRNGD_SOCKET"
elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then
$as_echo "#define OPENSSL_PRNG_ONLY 1" >>confdefs.h
RAND_MSG="OpenSSL internal ONLY"
elif test "x$openssl" = "xno" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&5
$as_echo "$as_me: WARNING: OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible" >&2;}
else
as_fn_error $? "OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options" "$LINENO" 5
fi
# Check for PAM libs
PAM_MSG="no"
# Check whether --with-pam was given.
if test "${with_pam+set}" = set; then :
withval=$with_pam;
if test "x$withval" != "xno" ; then
if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
as_fn_error $? "PAM headers not found" "$LINENO" 5
fi
saved_LIBS="$LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
$as_echo_n "checking for dlopen in -ldl... " >&6; }
if ${ac_cv_lib_dl_dlopen+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char dlopen ();
int
main ()
{
return dlopen ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_dl_dlopen=yes
else
ac_cv_lib_dl_dlopen=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBDL 1
_ACEOF
LIBS="-ldl $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_set_item in -lpam" >&5
$as_echo_n "checking for pam_set_item in -lpam... " >&6; }
if ${ac_cv_lib_pam_pam_set_item+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpam $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char pam_set_item ();
int
main ()
{
return pam_set_item ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_pam_pam_set_item=yes
else
ac_cv_lib_pam_pam_set_item=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_set_item" >&5
$as_echo "$ac_cv_lib_pam_pam_set_item" >&6; }
if test "x$ac_cv_lib_pam_pam_set_item" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBPAM 1
_ACEOF
LIBS="-lpam $LIBS"
else
as_fn_error $? "*** libpam missing" "$LINENO" 5
fi
for ac_func in pam_getenvlist
do :
ac_fn_c_check_func "$LINENO" "pam_getenvlist" "ac_cv_func_pam_getenvlist"
if test "x$ac_cv_func_pam_getenvlist" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PAM_GETENVLIST 1
_ACEOF
fi
done
for ac_func in pam_putenv
do :
ac_fn_c_check_func "$LINENO" "pam_putenv" "ac_cv_func_pam_putenv"
if test "x$ac_cv_func_pam_putenv" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PAM_PUTENV 1
_ACEOF
fi
done
LIBS="$saved_LIBS"
PAM_MSG="yes"
SSHDLIBS="$SSHDLIBS -lpam"
$as_echo "#define USE_PAM 1" >>confdefs.h
if test $ac_cv_lib_dl_dlopen = yes; then
case "$LIBS" in
*-ldl*)
# libdl already in LIBS
;;
*)
SSHDLIBS="$SSHDLIBS -ldl"
;;
esac
fi
fi
fi
# Check whether --with-pam-service was given.
if test "${with_pam_service+set}" = set; then :
withval=$with_pam_service;
if test "x$withval" != "xno" && \
test "x$withval" != "xyes" ; then
cat >>confdefs.h <<_ACEOF
#define SSHD_PAM_SERVICE "$withval"
_ACEOF
fi
fi
# Check for older PAM
if test "x$PAM_MSG" = "xyes" ; then
# Check PAM strerror arguments (old PAM)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pam_strerror takes only one argument" >&5
$as_echo_n "checking whether pam_strerror takes only one argument... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdlib.h>
#if defined(HAVE_SECURITY_PAM_APPL_H)
#include <security/pam_appl.h>
#elif defined (HAVE_PAM_PAM_APPL_H)
#include <pam/pam_appl.h>
#endif
int
main ()
{
(void)pam_strerror((pam_handle_t *)NULL, -1);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
else
$as_echo "#define HAVE_OLD_PAM 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
PAM_MSG="yes (old library)"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
case "$host" in
*-*-cygwin*)
SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER
;;
*)
SSH_PRIVSEP_USER=sshd
;;
esac
# Check whether --with-privsep-user was given.
if test "${with_privsep_user+set}" = set; then :
withval=$with_privsep_user;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
SSH_PRIVSEP_USER=$withval
fi
fi
if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then
cat >>confdefs.h <<_ACEOF
#define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER
_ACEOF
else
cat >>confdefs.h <<_ACEOF
#define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER"
_ACEOF
fi
if test "x$have_linux_no_new_privs" = "x1" ; then
ac_fn_c_check_decl "$LINENO" "SECCOMP_MODE_FILTER" "ac_cv_have_decl_SECCOMP_MODE_FILTER" "
#include <sys/types.h>
#include <linux/seccomp.h>
"
if test "x$ac_cv_have_decl_SECCOMP_MODE_FILTER" = xyes; then :
have_seccomp_filter=1
fi
fi
if test "x$have_seccomp_filter" = "x1" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking kernel for seccomp_filter support" >&5
$as_echo_n "checking kernel for seccomp_filter support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <errno.h>
#include <elf.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <stdlib.h>
#include <sys/prctl.h>
int
main ()
{
int i = $seccomp_audit_arch;
errno = 0;
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0);
exit(errno == EFAULT ? 0 : 1);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
# Disable seccomp filter as a target
have_seccomp_filter=0
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
# Decide which sandbox style to use
sandbox_arg=""
# Check whether --with-sandbox was given.
if test "${with_sandbox+set}" = set; then :
withval=$with_sandbox;
if test "x$withval" = "xyes" ; then
sandbox_arg=""
else
sandbox_arg="$withval"
fi
fi
# Some platforms (seems to be the ones that have a kernel poll(2)-type
# function with which they implement select(2)) use an extra file descriptor
# when calling select(2), which means we can't use the rlimit sandbox.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if select works with descriptor rlimit" >&5
$as_echo_n "checking if select works with descriptor rlimit... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
select_works_with_rlimit=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/resource.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
int
main ()
{
struct rlimit rl_zero;
int fd, r;
fd_set fds;
struct timeval tv;
fd = open("/dev/null", O_RDONLY);
FD_ZERO(&fds);
FD_SET(fd, &fds);
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
setrlimit(RLIMIT_FSIZE, &rl_zero);
setrlimit(RLIMIT_NOFILE, &rl_zero);
tv.tv_sec = 1;
tv.tv_usec = 0;
r = select(fd+1, &fds, NULL, NULL, &tv);
exit (r == -1 ? 1 : 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
select_works_with_rlimit=yes
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
select_works_with_rlimit=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if setrlimit(RLIMIT_NOFILE,{0,0}) works" >&5
$as_echo_n "checking if setrlimit(RLIMIT_NOFILE,{0,0}) works... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
rlimit_nofile_zero_works=yes
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/resource.h>
#include <errno.h>
#include <stdlib.h>
int
main ()
{
struct rlimit rl_zero;
int fd, r;
fd_set fds;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
r = setrlimit(RLIMIT_NOFILE, &rl_zero);
exit (r == -1 ? 1 : 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
rlimit_nofile_zero_works=yes
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
rlimit_nofile_zero_works=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if setrlimit RLIMIT_FSIZE works" >&5
$as_echo_n "checking if setrlimit RLIMIT_FSIZE works... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: assuming yes" >&5
$as_echo "$as_me: WARNING: cross compiling: assuming yes" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/resource.h>
#include <stdlib.h>
int
main ()
{
struct rlimit rl_zero;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
$as_echo "#define SANDBOX_SKIP_RLIMIT_FSIZE 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
if test "x$sandbox_arg" = "xpledge" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_pledge" = "xyes" ) ; then
test "x$ac_cv_func_pledge" != "xyes" && \
as_fn_error $? "pledge sandbox requires pledge(2) support" "$LINENO" 5
SANDBOX_STYLE="pledge"
$as_echo "#define SANDBOX_PLEDGE 1" >>confdefs.h
elif test "x$sandbox_arg" = "xsystrace" || \
( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
test "x$have_systr_policy_kill" != "x1" && \
as_fn_error $? "systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support" "$LINENO" 5
SANDBOX_STYLE="systrace"
$as_echo "#define SANDBOX_SYSTRACE 1" >>confdefs.h
elif test "x$sandbox_arg" = "xdarwin" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \
test "x$ac_cv_header_sandbox_h" = "xyes") ; then
test "x$ac_cv_func_sandbox_init" != "xyes" -o \
"x$ac_cv_header_sandbox_h" != "xyes" && \
as_fn_error $? "Darwin seatbelt sandbox requires sandbox.h and sandbox_init function" "$LINENO" 5
SANDBOX_STYLE="darwin"
$as_echo "#define SANDBOX_DARWIN 1" >>confdefs.h
elif test "x$sandbox_arg" = "xseccomp_filter" || \
( test -z "$sandbox_arg" && \
test "x$have_seccomp_filter" = "x1" && \
test "x$ac_cv_header_elf_h" = "xyes" && \
test "x$ac_cv_header_linux_audit_h" = "xyes" && \
test "x$ac_cv_header_linux_filter_h" = "xyes" && \
test "x$seccomp_audit_arch" != "x" && \
test "x$have_linux_no_new_privs" = "x1" && \
test "x$ac_cv_func_prctl" = "xyes" ) ; then
test "x$seccomp_audit_arch" = "x" && \
as_fn_error $? "seccomp_filter sandbox not supported on $host" "$LINENO" 5
test "x$have_linux_no_new_privs" != "x1" && \
as_fn_error $? "seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS" "$LINENO" 5
test "x$have_seccomp_filter" != "x1" && \
as_fn_error $? "seccomp_filter sandbox requires seccomp headers" "$LINENO" 5
test "x$ac_cv_func_prctl" != "xyes" && \
as_fn_error $? "seccomp_filter sandbox requires prctl function" "$LINENO" 5
SANDBOX_STYLE="seccomp_filter"
$as_echo "#define SANDBOX_SECCOMP_FILTER 1" >>confdefs.h
elif test "x$sandbox_arg" = "xcapsicum" || \
( test -z "$sandbox_arg" && \
test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \
test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \
as_fn_error $? "capsicum sandbox requires sys/capsicum.h header" "$LINENO" 5
test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
as_fn_error $? "capsicum sandbox requires cap_rights_limit function" "$LINENO" 5
SANDBOX_STYLE="capsicum"
$as_echo "#define SANDBOX_CAPSICUM 1" >>confdefs.h
elif test "x$sandbox_arg" = "xrlimit" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \
test "x$select_works_with_rlimit" = "xyes" && \
test "x$rlimit_nofile_zero_works" = "xyes" ) ; then
test "x$ac_cv_func_setrlimit" != "xyes" && \
as_fn_error $? "rlimit sandbox requires setrlimit function" "$LINENO" 5
test "x$select_works_with_rlimit" != "xyes" && \
as_fn_error $? "rlimit sandbox requires select to work with rlimit" "$LINENO" 5
SANDBOX_STYLE="rlimit"
$as_echo "#define SANDBOX_RLIMIT 1" >>confdefs.h
elif test "x$sandbox_arg" = "xsolaris" || \
( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then
SANDBOX_STYLE="solaris"
$as_echo "#define SANDBOX_SOLARIS 1" >>confdefs.h
elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
SANDBOX_STYLE="none"
$as_echo "#define SANDBOX_NULL 1" >>confdefs.h
else
as_fn_error $? "unsupported --with-sandbox" "$LINENO" 5
fi
# Cheap hack to ensure NEWS-OS libraries are arranged right.
if test ! -z "$SONY" ; then
LIBS="$LIBS -liberty";
fi
# Check for long long datatypes
ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"
if test "x$ac_cv_type_long_long" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LONG_LONG 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$ac_includes_default"
if test "x$ac_cv_type_unsigned_long_long" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UNSIGNED_LONG_LONG 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "long double" "ac_cv_type_long_double" "$ac_includes_default"
if test "x$ac_cv_type_long_double" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LONG_DOUBLE 1
_ACEOF
fi
# Check datatype sizes
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short int" >&5
$as_echo_n "checking size of short int... " >&6; }
if ${ac_cv_sizeof_short_int+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short int))" "ac_cv_sizeof_short_int" "$ac_includes_default"; then :
else
if test "$ac_cv_type_short_int" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (short int)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_short_int=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short_int" >&5
$as_echo "$ac_cv_sizeof_short_int" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_SHORT_INT $ac_cv_sizeof_short_int
_ACEOF
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
$as_echo_n "checking size of int... " >&6; }
if ${ac_cv_sizeof_int+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
else
if test "$ac_cv_type_int" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (int)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_int=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
$as_echo "$ac_cv_sizeof_int" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_INT $ac_cv_sizeof_int
_ACEOF
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long int" >&5
$as_echo_n "checking size of long int... " >&6; }
if ${ac_cv_sizeof_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long int))" "ac_cv_sizeof_long_int" "$ac_includes_default"; then :
else
if test "$ac_cv_type_long_int" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long int)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_long_int=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_int" >&5
$as_echo "$ac_cv_sizeof_long_int" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_LONG_INT $ac_cv_sizeof_long_int
_ACEOF
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long int" >&5
$as_echo_n "checking size of long long int... " >&6; }
if ${ac_cv_sizeof_long_long_int+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long int))" "ac_cv_sizeof_long_long_int" "$ac_includes_default"; then :
else
if test "$ac_cv_type_long_long_int" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (long long int)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_long_long_int=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long_int" >&5
$as_echo "$ac_cv_sizeof_long_long_int" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
_ACEOF
# Sanity check long long for some platforms (AIX)
if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
ac_cv_sizeof_long_long_int=0
fi
# compute LLONG_MIN and LLONG_MAX if we don't know them.
if test -z "$have_llong_max"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for max value of long long" >&5
$as_echo_n "checking for max value of long long... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
/* Why is this so damn hard? */
#ifdef __GNUC__
# undef __GNUC__
#endif
#define __USE_ISOC99
#include <limits.h>
#define DATA "conftest.llminmax"
#define my_abs(a) ((a) < 0 ? ((a) * -1) : (a))
/*
* printf in libc on some platforms (eg old Tru64) does not understand %lld so
* we do this the hard way.
*/
static int
fprint_ll(FILE *f, long long n)
{
unsigned int i;
int l[sizeof(long long) * 8];
if (n < 0)
if (fprintf(f, "-") < 0)
return -1;
for (i = 0; n != 0; i++) {
l[i] = my_abs(n % 10);
n /= 10;
}
do {
if (fprintf(f, "%d", l[--i]) < 0)
return -1;
} while (i != 0);
if (fprintf(f, " ") < 0)
return -1;
return 0;
}
int
main ()
{
FILE *f;
long long i, llmin, llmax = 0;
if((f = fopen(DATA,"w")) == NULL)
exit(1);
#if defined(LLONG_MIN) && defined(LLONG_MAX)
fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n");
llmin = LLONG_MIN;
llmax = LLONG_MAX;
#else
fprintf(stderr, "Calculating LLONG_MIN and LLONG_MAX\n");
/* This will work on one's complement and two's complement */
for (i = 1; i > llmax; i <<= 1, i++)
llmax = i;
llmin = llmax + 1LL; /* wrap */
#endif
/* Sanity check */
if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax
|| llmax - 1 > llmax || llmin == llmax || llmin == 0
|| llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) {
fprintf(f, "unknown unknown\n");
exit(2);
}
if (fprint_ll(f, llmin) < 0)
exit(3);
if (fprint_ll(f, llmax) < 0)
exit(4);
if (fclose(f) < 0)
exit(5);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
llong_min=`$AWK '{print $1}' conftest.llminmax`
llong_max=`$AWK '{print $2}' conftest.llminmax`
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $llong_max" >&5
$as_echo "$llong_max" >&6; }
cat >>confdefs.h <<_ACEOF
#define LLONG_MAX ${llong_max}LL
_ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for min value of long long" >&5
$as_echo_n "checking for min value of long long... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $llong_min" >&5
$as_echo "$llong_min" >&6; }
cat >>confdefs.h <<_ACEOF
#define LLONG_MIN ${llong_min}LL
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
$as_echo "not found" >&6; }
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
# More checks for data types
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int type" >&5
$as_echo_n "checking for u_int type... " >&6; }
if ${ac_cv_have_u_int+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
u_int a; a = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_u_int="yes"
else
ac_cv_have_u_int="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int" >&5
$as_echo "$ac_cv_have_u_int" >&6; }
if test "x$ac_cv_have_u_int" = "xyes" ; then
$as_echo "#define HAVE_U_INT 1" >>confdefs.h
have_u_int=1
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t types" >&5
$as_echo_n "checking for intXX_t types... " >&6; }
if ${ac_cv_have_intxx_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
int8_t a; int16_t b; int32_t c; a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_intxx_t="yes"
else
ac_cv_have_intxx_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_intxx_t" >&5
$as_echo "$ac_cv_have_intxx_t" >&6; }
if test "x$ac_cv_have_intxx_t" = "xyes" ; then
$as_echo "#define HAVE_INTXX_T 1" >>confdefs.h
have_intxx_t=1
fi
if (test -z "$have_intxx_t" && \
test "x$ac_cv_header_stdint_h" = "xyes")
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t types in stdint.h" >&5
$as_echo_n "checking for intXX_t types in stdint.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdint.h>
int
main ()
{
int8_t a; int16_t b; int32_t c; a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_INTXX_T 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for int64_t type" >&5
$as_echo_n "checking for int64_t type... " >&6; }
if ${ac_cv_have_int64_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <sys/socket.h>
#ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h>
#endif
int
main ()
{
int64_t a; a = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_int64_t="yes"
else
ac_cv_have_int64_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_int64_t" >&5
$as_echo "$ac_cv_have_int64_t" >&6; }
if test "x$ac_cv_have_int64_t" = "xyes" ; then
$as_echo "#define HAVE_INT64_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types" >&5
$as_echo_n "checking for u_intXX_t types... " >&6; }
if ${ac_cv_have_u_intxx_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_u_intxx_t="yes"
else
ac_cv_have_u_intxx_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_intxx_t" >&5
$as_echo "$ac_cv_have_u_intxx_t" >&6; }
if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then
$as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h
have_u_intxx_t=1
fi
if test -z "$have_u_intxx_t" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_intXX_t types in sys/socket.h" >&5
$as_echo_n "checking for u_intXX_t types in sys/socket.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/socket.h>
int
main ()
{
u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int64_t types" >&5
$as_echo_n "checking for u_int64_t types... " >&6; }
if ${ac_cv_have_u_int64_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
u_int64_t a; a = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_u_int64_t="yes"
else
ac_cv_have_u_int64_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_int64_t" >&5
$as_echo "$ac_cv_have_u_int64_t" >&6; }
if test "x$ac_cv_have_u_int64_t" = "xyes" ; then
$as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h
have_u_int64_t=1
fi
if (test -z "$have_u_int64_t" && \
test "x$ac_cv_header_sys_bitypes_h" = "xyes")
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_int64_t type in sys/bitypes.h" >&5
$as_echo_n "checking for u_int64_t type in sys/bitypes.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/bitypes.h>
int
main ()
{
u_int64_t a; a = 1
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_U_INT64_T 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if test -z "$have_u_intxx_t" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types" >&5
$as_echo_n "checking for uintXX_t types... " >&6; }
if ${ac_cv_have_uintxx_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
uint8_t a;
uint16_t b;
uint32_t c;
a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_uintxx_t="yes"
else
ac_cv_have_uintxx_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_uintxx_t" >&5
$as_echo "$ac_cv_have_uintxx_t" >&6; }
if test "x$ac_cv_have_uintxx_t" = "xyes" ; then
$as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h
fi
fi
if (test -z "$have_uintxx_t" && \
test "x$ac_cv_header_stdint_h" = "xyes")
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in stdint.h" >&5
$as_echo_n "checking for uintXX_t types in stdint.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdint.h>
int
main ()
{
uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if (test -z "$have_uintxx_t" && \
test "x$ac_cv_header_inttypes_h" = "xyes")
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uintXX_t types in inttypes.h" >&5
$as_echo_n "checking for uintXX_t types in inttypes.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <inttypes.h>
int
main ()
{
uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_UINTXX_T 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \
test "x$ac_cv_header_sys_bitypes_h" = "xyes")
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for intXX_t and u_intXX_t types in sys/bitypes.h" >&5
$as_echo_n "checking for intXX_t and u_intXX_t types in sys/bitypes.h... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/bitypes.h>
int
main ()
{
int8_t a; int16_t b; int32_t c;
u_int8_t e; u_int16_t f; u_int32_t g;
a = b = c = e = f = g = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
$as_echo "#define HAVE_U_INTXX_T 1" >>confdefs.h
$as_echo "#define HAVE_INTXX_T 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for u_char" >&5
$as_echo_n "checking for u_char... " >&6; }
if ${ac_cv_have_u_char+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
u_char foo; foo = 125;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_u_char="yes"
else
ac_cv_have_u_char="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_u_char" >&5
$as_echo "$ac_cv_have_u_char" >&6; }
if test "x$ac_cv_have_u_char" = "xyes" ; then
$as_echo "#define HAVE_U_CHAR 1" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "
#include <sys/types.h>
#include <stdint.h>
"
if test "x$ac_cv_type_intmax_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_INTMAX_T 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "
#include <sys/types.h>
#include <stdint.h>
"
if test "x$ac_cv_type_uintmax_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_UINTMAX_T 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include <sys/types.h>
#include <sys/socket.h>
"
if test "x$ac_cv_type_socklen_t" = xyes; then :
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5
$as_echo_n "checking for socklen_t equivalent... " >&6; }
if ${curl_cv_socklen_t_equiv+:} false; then :
$as_echo_n "(cached) " >&6
else
# Systems have either "struct sockaddr *" or
# "void *" as the second argument to getpeername
curl_cv_socklen_t_equiv=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int getpeername (int, $arg2 *, $t *);
int
main ()
{
$t len;
getpeername(0,0,&len);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
curl_cv_socklen_t_equiv="$t"
break
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
done
done
if test "x$curl_cv_socklen_t_equiv" = x; then
as_fn_error $? "Cannot find a type to use in place of socklen_t" "$LINENO" 5
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $curl_cv_socklen_t_equiv" >&5
$as_echo "$curl_cv_socklen_t_equiv" >&6; }
cat >>confdefs.h <<_ACEOF
#define socklen_t $curl_cv_socklen_t_equiv
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "sig_atomic_t" "ac_cv_type_sig_atomic_t" "#include <signal.h>
"
if test "x$ac_cv_type_sig_atomic_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SIG_ATOMIC_T 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "fsblkcnt_t" "ac_cv_type_fsblkcnt_t" "
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
"
if test "x$ac_cv_type_fsblkcnt_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FSBLKCNT_T 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "fsfilcnt_t" "ac_cv_type_fsfilcnt_t" "
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
"
if test "x$ac_cv_type_fsfilcnt_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_FSFILCNT_T 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct statfs" "f_flags" "ac_cv_member_struct_statfs_f_flags" "
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
"
if test "x$ac_cv_member_struct_statfs_f_flags" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STATFS_F_FLAGS 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "in_addr_t" "ac_cv_type_in_addr_t" "#include <sys/types.h>
#include <netinet/in.h>
"
if test "x$ac_cv_type_in_addr_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_IN_ADDR_T 1
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "in_port_t" "ac_cv_type_in_port_t" "#include <sys/types.h>
#include <netinet/in.h>
"
if test "x$ac_cv_type_in_port_t" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_IN_PORT_T 1
_ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for size_t" >&5
$as_echo_n "checking for size_t... " >&6; }
if ${ac_cv_have_size_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
size_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_size_t="yes"
else
ac_cv_have_size_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_size_t" >&5
$as_echo "$ac_cv_have_size_t" >&6; }
if test "x$ac_cv_have_size_t" = "xyes" ; then
$as_echo "#define HAVE_SIZE_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ssize_t" >&5
$as_echo_n "checking for ssize_t... " >&6; }
if ${ac_cv_have_ssize_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
ssize_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_ssize_t="yes"
else
ac_cv_have_ssize_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ssize_t" >&5
$as_echo "$ac_cv_have_ssize_t" >&6; }
if test "x$ac_cv_have_ssize_t" = "xyes" ; then
$as_echo "#define HAVE_SSIZE_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_t" >&5
$as_echo_n "checking for clock_t... " >&6; }
if ${ac_cv_have_clock_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <time.h>
int
main ()
{
clock_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_clock_t="yes"
else
ac_cv_have_clock_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_clock_t" >&5
$as_echo "$ac_cv_have_clock_t" >&6; }
if test "x$ac_cv_have_clock_t" = "xyes" ; then
$as_echo "#define HAVE_CLOCK_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sa_family_t" >&5
$as_echo_n "checking for sa_family_t... " >&6; }
if ${ac_cv_have_sa_family_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
sa_family_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_sa_family_t="yes"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int
main ()
{
sa_family_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_sa_family_t="yes"
else
ac_cv_have_sa_family_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_sa_family_t" >&5
$as_echo "$ac_cv_have_sa_family_t" >&6; }
if test "x$ac_cv_have_sa_family_t" = "xyes" ; then
$as_echo "#define HAVE_SA_FAMILY_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pid_t" >&5
$as_echo_n "checking for pid_t... " >&6; }
if ${ac_cv_have_pid_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
pid_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_pid_t="yes"
else
ac_cv_have_pid_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_pid_t" >&5
$as_echo "$ac_cv_have_pid_t" >&6; }
if test "x$ac_cv_have_pid_t" = "xyes" ; then
$as_echo "#define HAVE_PID_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mode_t" >&5
$as_echo_n "checking for mode_t... " >&6; }
if ${ac_cv_have_mode_t+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
main ()
{
mode_t foo; foo = 1235;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_mode_t="yes"
else
ac_cv_have_mode_t="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_mode_t" >&5
$as_echo "$ac_cv_have_mode_t" >&6; }
if test "x$ac_cv_have_mode_t" = "xyes" ; then
$as_echo "#define HAVE_MODE_T 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_storage" >&5
$as_echo_n "checking for struct sockaddr_storage... " >&6; }
if ${ac_cv_have_struct_sockaddr_storage+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
struct sockaddr_storage s;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_struct_sockaddr_storage="yes"
else
ac_cv_have_struct_sockaddr_storage="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_storage" >&5
$as_echo "$ac_cv_have_struct_sockaddr_storage" >&6; }
if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
$as_echo "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct sockaddr_in6" >&5
$as_echo_n "checking for struct sockaddr_in6... " >&6; }
if ${ac_cv_have_struct_sockaddr_in6+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <netinet/in.h>
int
main ()
{
struct sockaddr_in6 s; s.sin6_family = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_struct_sockaddr_in6="yes"
else
ac_cv_have_struct_sockaddr_in6="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_sockaddr_in6" >&5
$as_echo "$ac_cv_have_struct_sockaddr_in6" >&6; }
if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
$as_echo "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct in6_addr" >&5
$as_echo_n "checking for struct in6_addr... " >&6; }
if ${ac_cv_have_struct_in6_addr+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <netinet/in.h>
int
main ()
{
struct in6_addr s; s.s6_addr[0] = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_struct_in6_addr="yes"
else
ac_cv_have_struct_in6_addr="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_in6_addr" >&5
$as_echo "$ac_cv_have_struct_in6_addr" >&6; }
if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
$as_echo "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h
ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_scope_id" "ac_cv_member_struct_sockaddr_in6_sin6_scope_id" "
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>
"
if test "x$ac_cv_member_struct_sockaddr_in6_sin6_scope_id" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
_ACEOF
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct addrinfo" >&5
$as_echo_n "checking for struct addrinfo... " >&6; }
if ${ac_cv_have_struct_addrinfo+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int
main ()
{
struct addrinfo s; s.ai_flags = AI_PASSIVE;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_struct_addrinfo="yes"
else
ac_cv_have_struct_addrinfo="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_addrinfo" >&5
$as_echo "$ac_cv_have_struct_addrinfo" >&6; }
if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
$as_echo "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct timeval" >&5
$as_echo_n "checking for struct timeval... " >&6; }
if ${ac_cv_have_struct_timeval+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/time.h>
int
main ()
{
struct timeval tv; tv.tv_sec = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_struct_timeval="yes"
else
ac_cv_have_struct_timeval="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_struct_timeval" >&5
$as_echo "$ac_cv_have_struct_timeval" >&6; }
if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
$as_echo "#define HAVE_STRUCT_TIMEVAL 1" >>confdefs.h
have_struct_timeval=1
fi
ac_fn_c_check_type "$LINENO" "struct timespec" "ac_cv_type_struct_timespec" "$ac_includes_default"
if test "x$ac_cv_type_struct_timespec" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_TIMESPEC 1
_ACEOF
fi
# We need int64_t or else certain parts of the compile will fail.
if test "x$ac_cv_have_int64_t" = "xno" && \
test "x$ac_cv_sizeof_long_int" != "x8" && \
test "x$ac_cv_sizeof_long_long_int" = "x0" ; then
echo "OpenSSH requires int64_t support. Contact your vendor or install"
echo "an alternative compiler (I.E., GCC) before continuing."
echo ""
exit 1;
else
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Assuming working snprintf()" >&5
$as_echo "$as_me: WARNING: cross compiling: Assuming working snprintf()" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SNPRINTF
main()
{
char buf[50];
char expected_out[50];
int mazsize = 50 ;
#if (SIZEOF_LONG_INT == 8)
long int num = 0x7fffffffffffffff;
#else
long long num = 0x7fffffffffffffffll;
#endif
strcpy(expected_out, "9223372036854775807");
snprintf(buf, mazsize, "%lld", num);
if(strcmp(buf, expected_out) != 0)
exit(1);
exit(0);
}
#else
main() { exit(0); }
#endif
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
true
else
$as_echo "#define BROKEN_SNPRINTF 1" >>confdefs.h
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
# look for field 'ut_host' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmp.h" >&5
$as_echo_n "checking for ut_host field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_host" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_HOST_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_host' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_host
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_host field in utmpx.h" >&5
$as_echo_n "checking for ut_host field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_host" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_HOST_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'syslen' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"syslen
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for syslen field in utmpx.h" >&5
$as_echo_n "checking for syslen field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "syslen" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_SYSLEN_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_pid' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_pid
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_pid field in utmp.h" >&5
$as_echo_n "checking for ut_pid field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_pid" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_PID_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_type' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmp.h" >&5
$as_echo_n "checking for ut_type field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_type" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_TYPE_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_type' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_type
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_type field in utmpx.h" >&5
$as_echo_n "checking for ut_type field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_type" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_TYPE_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_tv' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmp.h" >&5
$as_echo_n "checking for ut_tv field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_tv" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_TV_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_id' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmp.h" >&5
$as_echo_n "checking for ut_id field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_id" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_ID_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_id' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_id
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_id field in utmpx.h" >&5
$as_echo_n "checking for ut_id field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_id" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_ID_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_addr' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmp.h" >&5
$as_echo_n "checking for ut_addr field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_addr" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_ADDR_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_addr' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr field in utmpx.h" >&5
$as_echo_n "checking for ut_addr field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_addr" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_ADDR_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_addr_v6' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmp.h" >&5
$as_echo_n "checking for ut_addr_v6 field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_addr_v6" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_ADDR_V6_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_addr_v6' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_addr_v6
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_addr_v6 field in utmpx.h" >&5
$as_echo_n "checking for ut_addr_v6 field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_addr_v6" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_ADDR_V6_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_exit' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_exit
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_exit field in utmp.h" >&5
$as_echo_n "checking for ut_exit field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_exit" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_EXIT_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_time' in header 'utmp.h'
ossh_safe=`echo "utmp.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmp.h" >&5
$as_echo_n "checking for ut_time field in utmp.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmp.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_time" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_TIME_IN_UTMP 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_time' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_time
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_time field in utmpx.h" >&5
$as_echo_n "checking for ut_time field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_time" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_TIME_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# look for field 'ut_tv' in header 'utmpx.h'
ossh_safe=`echo "utmpx.h" | sed 'y%./+-%__p_%'`
ossh_varname="ossh_cv_$ossh_safe""_has_"ut_tv
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ut_tv field in utmpx.h" >&5
$as_echo_n "checking for ut_tv field in utmpx.h... " >&6; }
if eval \${$ossh_varname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <utmpx.h>
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
$EGREP "ut_tv" >/dev/null 2>&1; then :
eval "$ossh_varname=yes"
else
eval "$ossh_varname=no"
fi
rm -f conftest*
fi
ossh_result=`eval 'echo $'"$ossh_varname"`
if test -n "`echo $ossh_varname`"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ossh_result" >&5
$as_echo "$ossh_result" >&6; }
if test "x$ossh_result" = "xyes"; then
$as_echo "#define HAVE_TV_IN_UTMPX 1" >>confdefs.h
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_MTIM 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtime" "ac_cv_member_struct_stat_st_mtime" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_mtime" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_MTIME 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct passwd" "pw_gecos" "ac_cv_member_struct_passwd_pw_gecos" "
#include <sys/types.h>
#include <pwd.h>
"
if test "x$ac_cv_member_struct_passwd_pw_gecos" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_PASSWD_PW_GECOS 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct passwd" "pw_class" "ac_cv_member_struct_passwd_pw_class" "
#include <sys/types.h>
#include <pwd.h>
"
if test "x$ac_cv_member_struct_passwd_pw_class" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_PASSWD_PW_CLASS 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct passwd" "pw_change" "ac_cv_member_struct_passwd_pw_change" "
#include <sys/types.h>
#include <pwd.h>
"
if test "x$ac_cv_member_struct_passwd_pw_change" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_PASSWD_PW_CHANGE 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct passwd" "pw_expire" "ac_cv_member_struct_passwd_pw_expire" "
#include <sys/types.h>
#include <pwd.h>
"
if test "x$ac_cv_member_struct_passwd_pw_expire" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_PASSWD_PW_EXPIRE 1
_ACEOF
fi
ac_fn_c_check_member "$LINENO" "struct __res_state" "retrans" "ac_cv_member_struct___res_state_retrans" "
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
"
if test "x$ac_cv_member_struct___res_state_retrans" = xyes; then :
else
$as_echo "#define __res_state state" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ss_family field in struct sockaddr_storage" >&5
$as_echo_n "checking for ss_family field in struct sockaddr_storage... " >&6; }
if ${ac_cv_have_ss_family_in_struct_ss+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
struct sockaddr_storage s; s.ss_family = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_ss_family_in_struct_ss="yes"
else
ac_cv_have_ss_family_in_struct_ss="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_ss_family_in_struct_ss" >&5
$as_echo "$ac_cv_have_ss_family_in_struct_ss" >&6; }
if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
$as_echo "#define HAVE_SS_FAMILY_IN_SS 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __ss_family field in struct sockaddr_storage" >&5
$as_echo_n "checking for __ss_family field in struct sockaddr_storage... " >&6; }
if ${ac_cv_have___ss_family_in_struct_ss+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
int
main ()
{
struct sockaddr_storage s; s.__ss_family = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have___ss_family_in_struct_ss="yes"
else
ac_cv_have___ss_family_in_struct_ss="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___ss_family_in_struct_ss" >&5
$as_echo "$ac_cv_have___ss_family_in_struct_ss" >&6; }
if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
$as_echo "#define HAVE___SS_FAMILY_IN_SS 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for msg_accrights field in struct msghdr" >&5
$as_echo_n "checking for msg_accrights field in struct msghdr... " >&6; }
if ${ac_cv_have_accrights_in_msghdr+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
int
main ()
{
#ifdef msg_accrights
#error "msg_accrights is a macro"
exit(1);
#endif
struct msghdr m;
m.msg_accrights = 0;
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_accrights_in_msghdr="yes"
else
ac_cv_have_accrights_in_msghdr="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_accrights_in_msghdr" >&5
$as_echo "$ac_cv_have_accrights_in_msghdr" >&6; }
if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then
$as_echo "#define HAVE_ACCRIGHTS_IN_MSGHDR 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct statvfs.f_fsid is integral type" >&5
$as_echo_n "checking if struct statvfs.f_fsid is integral type... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/param.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
int
main ()
{
struct statvfs s; s.f_fsid = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if fsid_t has member val" >&5
$as_echo_n "checking if fsid_t has member val... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/statvfs.h>
int
main ()
{
fsid_t t; t.val[0] = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define FSID_HAS_VAL 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if f_fsid has member __val" >&5
$as_echo_n "checking if f_fsid has member __val... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/statvfs.h>
int
main ()
{
fsid_t t; t.__val[0] = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define FSID_HAS___VAL 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for msg_control field in struct msghdr" >&5
$as_echo_n "checking for msg_control field in struct msghdr... " >&6; }
if ${ac_cv_have_control_in_msghdr+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
int
main ()
{
#ifdef msg_control
#error "msg_control is a macro"
exit(1);
#endif
struct msghdr m;
m.msg_control = 0;
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
ac_cv_have_control_in_msghdr="yes"
else
ac_cv_have_control_in_msghdr="no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_control_in_msghdr" >&5
$as_echo "$ac_cv_have_control_in_msghdr" >&6; }
if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then
$as_echo "#define HAVE_CONTROL_IN_MSGHDR 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines __progname" >&5
$as_echo_n "checking if libc defines __progname... " >&6; }
if ${ac_cv_libc_defines___progname+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
extern char *__progname; printf("%s", __progname);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_libc_defines___progname="yes"
else
ac_cv_libc_defines___progname="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines___progname" >&5
$as_echo "$ac_cv_libc_defines___progname" >&6; }
if test "x$ac_cv_libc_defines___progname" = "xyes" ; then
$as_echo "#define HAVE___PROGNAME 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __FUNCTION__" >&5
$as_echo_n "checking whether $CC implements __FUNCTION__... " >&6; }
if ${ac_cv_cc_implements___FUNCTION__+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
printf("%s", __FUNCTION__);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_cc_implements___FUNCTION__="yes"
else
ac_cv_cc_implements___FUNCTION__="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___FUNCTION__" >&5
$as_echo "$ac_cv_cc_implements___FUNCTION__" >&6; }
if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then
$as_echo "#define HAVE___FUNCTION__ 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC implements __func__" >&5
$as_echo_n "checking whether $CC implements __func__... " >&6; }
if ${ac_cv_cc_implements___func__+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
main ()
{
printf("%s", __func__);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_cc_implements___func__="yes"
else
ac_cv_cc_implements___func__="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_implements___func__" >&5
$as_echo "$ac_cv_cc_implements___func__" >&6; }
if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
$as_echo "#define HAVE___func__ 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether va_copy exists" >&5
$as_echo_n "checking whether va_copy exists... " >&6; }
if ${ac_cv_have_va_copy+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
va_list x,y;
int
main ()
{
va_copy(x,y);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_have_va_copy="yes"
else
ac_cv_have_va_copy="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_va_copy" >&5
$as_echo "$ac_cv_have_va_copy" >&6; }
if test "x$ac_cv_have_va_copy" = "xyes" ; then
$as_echo "#define HAVE_VA_COPY 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __va_copy exists" >&5
$as_echo_n "checking whether __va_copy exists... " >&6; }
if ${ac_cv_have___va_copy+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdarg.h>
va_list x,y;
int
main ()
{
__va_copy(x,y);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_have___va_copy="yes"
else
ac_cv_have___va_copy="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have___va_copy" >&5
$as_echo "$ac_cv_have___va_copy" >&6; }
if test "x$ac_cv_have___va_copy" = "xyes" ; then
$as_echo "#define HAVE___VA_COPY 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether getopt has optreset support" >&5
$as_echo_n "checking whether getopt has optreset support... " >&6; }
if ${ac_cv_have_getopt_optreset+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <getopt.h>
int
main ()
{
extern int optreset; optreset = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_have_getopt_optreset="yes"
else
ac_cv_have_getopt_optreset="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_getopt_optreset" >&5
$as_echo "$ac_cv_have_getopt_optreset" >&6; }
if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
$as_echo "#define HAVE_GETOPT_OPTRESET 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_errlist" >&5
$as_echo_n "checking if libc defines sys_errlist... " >&6; }
if ${ac_cv_libc_defines_sys_errlist+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_libc_defines_sys_errlist="yes"
else
ac_cv_libc_defines_sys_errlist="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_errlist" >&5
$as_echo "$ac_cv_libc_defines_sys_errlist" >&6; }
if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then
$as_echo "#define HAVE_SYS_ERRLIST 1" >>confdefs.h
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libc defines sys_nerr" >&5
$as_echo_n "checking if libc defines sys_nerr... " >&6; }
if ${ac_cv_libc_defines_sys_nerr+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
main ()
{
extern int sys_nerr; printf("%i", sys_nerr);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_libc_defines_sys_nerr="yes"
else
ac_cv_libc_defines_sys_nerr="no"
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libc_defines_sys_nerr" >&5
$as_echo "$ac_cv_libc_defines_sys_nerr" >&6; }
if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
$as_echo "#define HAVE_SYS_NERR 1" >>confdefs.h
fi
# Check libraries needed by DNS fingerprint support
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getrrsetbyname" >&5
$as_echo_n "checking for library containing getrrsetbyname... " >&6; }
if ${ac_cv_search_getrrsetbyname+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char getrrsetbyname ();
int
main ()
{
return getrrsetbyname ();
;
return 0;
}
_ACEOF
for ac_lib in '' resolv; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_getrrsetbyname=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_getrrsetbyname+:} false; then :
break
fi
done
if ${ac_cv_search_getrrsetbyname+:} false; then :
else
ac_cv_search_getrrsetbyname=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrrsetbyname" >&5
$as_echo "$ac_cv_search_getrrsetbyname" >&6; }
ac_res=$ac_cv_search_getrrsetbyname
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$as_echo "#define HAVE_GETRRSETBYNAME 1" >>confdefs.h
else
# Needed by our getrrsetbyname()
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing res_query" >&5
$as_echo_n "checking for library containing res_query... " >&6; }
if ${ac_cv_search_res_query+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char res_query ();
int
main ()
{
return res_query ();
;
return 0;
}
_ACEOF
for ac_lib in '' resolv; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_res_query=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_res_query+:} false; then :
break
fi
done
if ${ac_cv_search_res_query+:} false; then :
else
ac_cv_search_res_query=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_query" >&5
$as_echo "$ac_cv_search_res_query" >&6; }
ac_res=$ac_cv_search_res_query
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5
$as_echo_n "checking for library containing dn_expand... " >&6; }
if ${ac_cv_search_dn_expand+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char dn_expand ();
int
main ()
{
return dn_expand ();
;
return 0;
}
_ACEOF
for ac_lib in '' resolv; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_dn_expand=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_dn_expand+:} false; then :
break
fi
done
if ${ac_cv_search_dn_expand+:} false; then :
else
ac_cv_search_dn_expand=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5
$as_echo "$ac_cv_search_dn_expand" >&6; }
ac_res=$ac_cv_search_dn_expand
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if res_query will link" >&5
$as_echo_n "checking if res_query will link... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
int
main ()
{
res_query (0, 0, 0, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
saved_LIBS="$LIBS"
LIBS="$LIBS -lresolv"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query in -lresolv" >&5
$as_echo_n "checking for res_query in -lresolv... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
int
main ()
{
res_query (0, 0, 0, 0, 0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
LIBS="$saved_LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
for ac_func in _getshort _getlong
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
ac_fn_c_check_decl "$LINENO" "_getshort" "ac_cv_have_decl__getshort" "#include <sys/types.h>
#include <arpa/nameser.h>
"
if test "x$ac_cv_have_decl__getshort" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL__GETSHORT $ac_have_decl
_ACEOF
ac_fn_c_check_decl "$LINENO" "_getlong" "ac_cv_have_decl__getlong" "#include <sys/types.h>
#include <arpa/nameser.h>
"
if test "x$ac_cv_have_decl__getlong" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL__GETLONG $ac_have_decl
_ACEOF
ac_fn_c_check_member "$LINENO" "HEADER" "ad" "ac_cv_member_HEADER_ad" "#include <arpa/nameser.h>
"
if test "x$ac_cv_member_HEADER_ad" = xyes; then :
$as_echo "#define HAVE_HEADER_AD 1" >>confdefs.h
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct __res_state _res is an extern" >&5
$as_echo_n "checking if struct __res_state _res is an extern... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
extern struct __res_state _res;
int
main ()
{
struct __res_state *volatile p = &_res; /* force resolution of _res */
return 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE__RES_EXTERN 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
# Check whether user wants SELinux support
SELINUX_MSG="no"
LIBSELINUX=""
# Check whether --with-selinux was given.
if test "${with_selinux+set}" = set; then :
withval=$with_selinux; if test "x$withval" != "xno" ; then
save_LIBS="$LIBS"
$as_echo "#define WITH_SELINUX 1" >>confdefs.h
SELINUX_MSG="yes"
ac_fn_c_check_header_mongrel "$LINENO" "selinux/selinux.h" "ac_cv_header_selinux_selinux_h" "$ac_includes_default"
if test "x$ac_cv_header_selinux_selinux_h" = xyes; then :
else
as_fn_error $? "SELinux support requires selinux.h header" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for setexeccon in -lselinux" >&5
$as_echo_n "checking for setexeccon in -lselinux... " >&6; }
if ${ac_cv_lib_selinux_setexeccon+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lselinux $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char setexeccon ();
int
main ()
{
return setexeccon ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_selinux_setexeccon=yes
else
ac_cv_lib_selinux_setexeccon=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_selinux_setexeccon" >&5
$as_echo "$ac_cv_lib_selinux_setexeccon" >&6; }
if test "x$ac_cv_lib_selinux_setexeccon" = xyes; then :
LIBSELINUX="-lselinux"
LIBS="$LIBS -lselinux"
else
as_fn_error $? "SELinux support requires libselinux library" "$LINENO" 5
fi
SSHLIBS="$SSHLIBS $LIBSELINUX"
SSHDLIBS="$SSHDLIBS $LIBSELINUX"
for ac_func in getseuserbyname get_default_context_with_level
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
LIBS="$save_LIBS"
fi
fi
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
# Check whether --with-kerberos5 was given.
if test "${with_kerberos5+set}" = set; then :
withval=$with_kerberos5; if test "x$withval" != "xno" ; then
if test "x$withval" = "xyes" ; then
KRB5ROOT="/usr/local"
else
KRB5ROOT=${withval}
fi
$as_echo "#define KRB5 1" >>confdefs.h
KRB5_MSG="yes"
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}krb5-config", so it can be a program name with args.
set dummy ${ac_tool_prefix}krb5-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_KRB5CONF+:} false; then :
$as_echo_n "(cached) " >&6
else
case $KRB5CONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_KRB5CONF="$KRB5CONF" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_dummy="$KRB5ROOT/bin:$PATH"
for as_dir in $as_dummy
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_KRB5CONF="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
KRB5CONF=$ac_cv_path_KRB5CONF
if test -n "$KRB5CONF"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $KRB5CONF" >&5
$as_echo "$KRB5CONF" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
if test -z "$ac_cv_path_KRB5CONF"; then
ac_pt_KRB5CONF=$KRB5CONF
# Extract the first word of "krb5-config", so it can be a program name with args.
set dummy krb5-config; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_ac_pt_KRB5CONF+:} false; then :
$as_echo_n "(cached) " >&6
else
case $ac_pt_KRB5CONF in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_KRB5CONF="$ac_pt_KRB5CONF" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_dummy="$KRB5ROOT/bin:$PATH"
for as_dir in $as_dummy
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_ac_pt_KRB5CONF="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
ac_pt_KRB5CONF=$ac_cv_path_ac_pt_KRB5CONF
if test -n "$ac_pt_KRB5CONF"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_KRB5CONF" >&5
$as_echo "$ac_pt_KRB5CONF" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "x$ac_pt_KRB5CONF" = x; then
KRB5CONF="$KRB5ROOT/bin/krb5-config"
else
case $cross_compiling:$ac_tool_warned in
yes:)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
KRB5CONF=$ac_pt_KRB5CONF
fi
else
KRB5CONF="$ac_cv_path_KRB5CONF"
fi
if test -x $KRB5CONF ; then
K5CFLAGS="`$KRB5CONF --cflags`"
K5LIBS="`$KRB5CONF --libs`"
CPPFLAGS="$CPPFLAGS $K5CFLAGS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gssapi support" >&5
$as_echo_n "checking for gssapi support... " >&6; }
if $KRB5CONF | grep gssapi >/dev/null ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define GSSAPI 1" >>confdefs.h
GSSCFLAGS="`$KRB5CONF --cflags gssapi`"
GSSLIBS="`$KRB5CONF --libs gssapi`"
CPPFLAGS="$CPPFLAGS $GSSCFLAGS"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5
$as_echo_n "checking whether we are using Heimdal... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <krb5.h>
int
main ()
{
char *tmp = heimdal_version;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HEIMDAL 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
else
CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5
$as_echo_n "checking whether we are using Heimdal... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <krb5.h>
int
main ()
{
char *tmp = heimdal_version;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HEIMDAL 1" >>confdefs.h
K5LIBS="-lkrb5"
K5LIBS="$K5LIBS -lcom_err -lasn1"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for net_write in -lroken" >&5
$as_echo_n "checking for net_write in -lroken... " >&6; }
if ${ac_cv_lib_roken_net_write+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lroken $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char net_write ();
int
main ()
{
return net_write ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_roken_net_write=yes
else
ac_cv_lib_roken_net_write=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_roken_net_write" >&5
$as_echo "$ac_cv_lib_roken_net_write" >&6; }
if test "x$ac_cv_lib_roken_net_write" = xyes; then :
K5LIBS="$K5LIBS -lroken"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for des_cbc_encrypt in -ldes" >&5
$as_echo_n "checking for des_cbc_encrypt in -ldes... " >&6; }
if ${ac_cv_lib_des_des_cbc_encrypt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldes $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char des_cbc_encrypt ();
int
main ()
{
return des_cbc_encrypt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_des_des_cbc_encrypt=yes
else
ac_cv_lib_des_des_cbc_encrypt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_des_des_cbc_encrypt" >&5
$as_echo "$ac_cv_lib_des_des_cbc_encrypt" >&6; }
if test "x$ac_cv_lib_des_des_cbc_encrypt" = xyes; then :
K5LIBS="$K5LIBS -ldes"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
K5LIBS="-lkrb5 -lk5crypto -lcom_err"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dn_expand" >&5
$as_echo_n "checking for library containing dn_expand... " >&6; }
if ${ac_cv_search_dn_expand+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char dn_expand ();
int
main ()
{
return dn_expand ();
;
return 0;
}
_ACEOF
for ac_lib in '' resolv; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_dn_expand=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_dn_expand+:} false; then :
break
fi
done
if ${ac_cv_search_dn_expand+:} false; then :
else
ac_cv_search_dn_expand=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dn_expand" >&5
$as_echo "$ac_cv_search_dn_expand" >&6; }
ac_res=$ac_cv_search_dn_expand
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi_krb5" >&5
$as_echo_n "checking for gss_init_sec_context in -lgssapi_krb5... " >&6; }
if ${ac_cv_lib_gssapi_krb5_gss_init_sec_context+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgssapi_krb5 $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char gss_init_sec_context ();
int
main ()
{
return gss_init_sec_context ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_gssapi_krb5_gss_init_sec_context=yes
else
ac_cv_lib_gssapi_krb5_gss_init_sec_context=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&5
$as_echo "$ac_cv_lib_gssapi_krb5_gss_init_sec_context" >&6; }
if test "x$ac_cv_lib_gssapi_krb5_gss_init_sec_context" = xyes; then :
$as_echo "#define GSSAPI 1" >>confdefs.h
GSSLIBS="-lgssapi_krb5"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgssapi" >&5
$as_echo_n "checking for gss_init_sec_context in -lgssapi... " >&6; }
if ${ac_cv_lib_gssapi_gss_init_sec_context+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgssapi $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char gss_init_sec_context ();
int
main ()
{
return gss_init_sec_context ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_gssapi_gss_init_sec_context=yes
else
ac_cv_lib_gssapi_gss_init_sec_context=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gssapi_gss_init_sec_context" >&5
$as_echo "$ac_cv_lib_gssapi_gss_init_sec_context" >&6; }
if test "x$ac_cv_lib_gssapi_gss_init_sec_context" = xyes; then :
$as_echo "#define GSSAPI 1" >>confdefs.h
GSSLIBS="-lgssapi"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gss_init_sec_context in -lgss" >&5
$as_echo_n "checking for gss_init_sec_context in -lgss... " >&6; }
if ${ac_cv_lib_gss_gss_init_sec_context+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lgss $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char gss_init_sec_context ();
int
main ()
{
return gss_init_sec_context ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_gss_gss_init_sec_context=yes
else
ac_cv_lib_gss_gss_init_sec_context=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gss_gss_init_sec_context" >&5
$as_echo "$ac_cv_lib_gss_gss_init_sec_context" >&6; }
if test "x$ac_cv_lib_gss_gss_init_sec_context" = xyes; then :
$as_echo "#define GSSAPI 1" >>confdefs.h
GSSLIBS="-lgss"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api library - build may fail" >&5
$as_echo "$as_me: WARNING: Cannot find any suitable gss-api library - build may fail" >&2;}
fi
fi
fi
ac_fn_c_check_header_mongrel "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default"
if test "x$ac_cv_header_gssapi_h" = xyes; then :
else
unset ac_cv_header_gssapi_h
CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
for ac_header in gssapi.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "gssapi.h" "ac_cv_header_gssapi_h" "$ac_includes_default"
if test "x$ac_cv_header_gssapi_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GSSAPI_H 1
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find any suitable gss-api header - build may fail" >&5
$as_echo "$as_me: WARNING: Cannot find any suitable gss-api header - build may fail" >&2;}
fi
done
fi
oldCPP="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
ac_fn_c_check_header_mongrel "$LINENO" "gssapi_krb5.h" "ac_cv_header_gssapi_krb5_h" "$ac_includes_default"
if test "x$ac_cv_header_gssapi_krb5_h" = xyes; then :
else
CPPFLAGS="$oldCPP"
fi
fi
- if test ! -z "$need_dash_r" ; then
- LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
+ if test -n "${rpath_opt}" ; then
+ LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib"
fi
if test ! -z "$blibpath" ; then
blibpath="$blibpath:${KRB5ROOT}/lib"
fi
for ac_header in gssapi.h gssapi/gssapi.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_header in gssapi_krb5.h gssapi/gssapi_krb5.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_header in gssapi_generic.h gssapi/gssapi_generic.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing k_hasafs" >&5
$as_echo_n "checking for library containing k_hasafs... " >&6; }
if ${ac_cv_search_k_hasafs+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char k_hasafs ();
int
main ()
{
return k_hasafs ();
;
return 0;
}
_ACEOF
for ac_lib in '' kafs; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_search_k_hasafs=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
if ${ac_cv_search_k_hasafs+:} false; then :
break
fi
done
if ${ac_cv_search_k_hasafs+:} false; then :
else
ac_cv_search_k_hasafs=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_k_hasafs" >&5
$as_echo "$ac_cv_search_k_hasafs" >&6; }
ac_res=$ac_cv_search_k_hasafs
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
$as_echo "#define USE_AFS 1" >>confdefs.h
fi
ac_fn_c_check_decl "$LINENO" "GSS_C_NT_HOSTBASED_SERVICE" "ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" "
#ifdef HAVE_GSSAPI_H
# include <gssapi.h>
#elif defined(HAVE_GSSAPI_GSSAPI_H)
# include <gssapi/gssapi.h>
#endif
#ifdef HAVE_GSSAPI_GENERIC_H
# include <gssapi_generic.h>
#elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H)
# include <gssapi/gssapi_generic.h>
#endif
"
if test "x$ac_cv_have_decl_GSS_C_NT_HOSTBASED_SERVICE" = xyes; then :
ac_have_decl=1
else
ac_have_decl=0
fi
cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE $ac_have_decl
_ACEOF
saved_LIBS="$LIBS"
LIBS="$LIBS $K5LIBS"
for ac_func in krb5_cc_new_unique krb5_get_error_message krb5_free_error_message
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
LIBS="$saved_LIBS"
fi
fi
# Looking for programs, paths and files
PRIVSEP_PATH=/var/empty
# Check whether --with-privsep-path was given.
if test "${with_privsep_path+set}" = set; then :
withval=$with_privsep_path;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
PRIVSEP_PATH=$withval
fi
fi
# Check whether --with-xauth was given.
if test "${with_xauth+set}" = set; then :
withval=$with_xauth;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
xauth_path=$withval
fi
else
TestPath="$PATH"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin"
# Extract the first word of "xauth", so it can be a program name with args.
set dummy xauth; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_xauth_path+:} false; then :
$as_echo_n "(cached) " >&6
else
case $xauth_path in
[\\/]* | ?:[\\/]*)
ac_cv_path_xauth_path="$xauth_path" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $TestPath
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_xauth_path="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
xauth_path=$ac_cv_path_xauth_path
if test -n "$xauth_path"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xauth_path" >&5
$as_echo "$xauth_path" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then
xauth_path="/usr/openwin/bin/xauth"
fi
fi
STRIP_OPT=-s
# Check whether --enable-strip was given.
if test "${enable_strip+set}" = set; then :
enableval=$enable_strip;
if test "x$enableval" = "xno" ; then
STRIP_OPT=
fi
fi
if test -z "$xauth_path" ; then
XAUTH_PATH="undefined"
else
cat >>confdefs.h <<_ACEOF
#define XAUTH_PATH "$xauth_path"
_ACEOF
XAUTH_PATH=$xauth_path
fi
# Check for mail directory
# Check whether --with-maildir was given.
if test "${with_maildir+set}" = set; then :
withval=$with_maildir;
if test "X$withval" != X && test "x$withval" != xno && \
test "x${withval}" != xyes; then
cat >>confdefs.h <<_ACEOF
#define MAIL_DIRECTORY "$withval"
_ACEOF
fi
else
if test "X$maildir" != "X"; then
cat >>confdefs.h <<_ACEOF
#define MAIL_DIRECTORY "$maildir"
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Discovering system mail directory" >&5
$as_echo_n "checking Discovering system mail directory... " >&6; }
if test "$cross_compiling" = yes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&5
$as_echo "$as_me: WARNING: cross compiling: use --with-maildir=/path/to/mail" >&2;}
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <string.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef HAVE_MAILLOCK_H
#include <maillock.h>
#endif
#define DATA "conftest.maildir"
int
main ()
{
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
#if defined (_PATH_MAILDIR)
if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0)
exit(1);
#elif defined (MAILDIR)
if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0)
exit(1);
#elif defined (_PATH_MAIL)
if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0)
exit(1);
#else
exit (2);
#endif
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
maildir_what=`awk -F: '{print $1}' conftest.maildir`
maildir=`awk -F: '{print $2}' conftest.maildir \
| sed 's|/$||'`
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using: $maildir from $maildir_what" >&5
$as_echo "Using: $maildir from $maildir_what" >&6; }
if test "x$maildir_what" != "x_PATH_MAILDIR"; then
cat >>confdefs.h <<_ACEOF
#define MAIL_DIRECTORY "$maildir"
_ACEOF
fi
else
if test "X$ac_status" = "X2";then
# our test program didn't find it. Default to /var/spool/mail
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using: default value of /var/spool/mail" >&5
$as_echo "Using: default value of /var/spool/mail" >&6; }
cat >>confdefs.h <<_ACEOF
#define MAIL_DIRECTORY "/var/spool/mail"
_ACEOF
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: *** not found ***" >&5
$as_echo "*** not found ***" >&6; }
fi
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
fi
# maildir
if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptmx test" >&5
$as_echo "$as_me: WARNING: cross compiling: Disabling /dev/ptmx test" >&2;}
disable_ptmx_check=yes
fi
if test -z "$no_dev_ptmx" ; then
if test "x$disable_ptmx_check" != "xyes" ; then
as_ac_File=`$as_echo "ac_cv_file_"/dev/ptmx"" | $as_tr_sh`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptmx\"" >&5
$as_echo_n "checking for \"/dev/ptmx\"... " >&6; }
if eval \${$as_ac_File+:} false; then :
$as_echo_n "(cached) " >&6
else
test "$cross_compiling" = yes &&
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
if test -r ""/dev/ptmx""; then
eval "$as_ac_File=yes"
else
eval "$as_ac_File=no"
fi
fi
eval ac_res=\$$as_ac_File
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_DEV_PTMX 1
_ACEOF
have_dev_ptmx=1
fi
fi
fi
if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then
as_ac_File=`$as_echo "ac_cv_file_"/dev/ptc"" | $as_tr_sh`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/dev/ptc\"" >&5
$as_echo_n "checking for \"/dev/ptc\"... " >&6; }
if eval \${$as_ac_File+:} false; then :
$as_echo_n "(cached) " >&6
else
test "$cross_compiling" = yes &&
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
if test -r ""/dev/ptc""; then
eval "$as_ac_File=yes"
else
eval "$as_ac_File=no"
fi
fi
eval ac_res=\$$as_ac_File
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_DEV_PTS_AND_PTC 1
_ACEOF
have_dev_ptc=1
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: Disabling /dev/ptc test" >&5
$as_echo "$as_me: WARNING: cross compiling: Disabling /dev/ptc test" >&2;}
fi
# Options from here on. Some of these are preset by platform above
# Check whether --with-mantype was given.
if test "${with_mantype+set}" = set; then :
withval=$with_mantype;
case "$withval" in
man|cat|doc)
MANTYPE=$withval
;;
*)
as_fn_error $? "invalid man type: $withval" "$LINENO" 5
;;
esac
fi
if test -z "$MANTYPE"; then
TestPath="/usr/bin${PATH_SEPARATOR}/usr/ucb"
for ac_prog in nroff awf
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_NROFF+:} false; then :
$as_echo_n "(cached) " >&6
else
case $NROFF in
[\\/]* | ?:[\\/]*)
ac_cv_path_NROFF="$NROFF" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $TestPath
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_NROFF="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
NROFF=$ac_cv_path_NROFF
if test -n "$NROFF"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NROFF" >&5
$as_echo "$NROFF" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$NROFF" && break
done
test -n "$NROFF" || NROFF="/bin/false"
if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
MANTYPE=doc
elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then
MANTYPE=man
else
MANTYPE=cat
fi
fi
if test "$MANTYPE" = "doc"; then
mansubdir=man;
else
mansubdir=$MANTYPE;
fi
# Check whether to enable MD5 passwords
MD5_MSG="no"
# Check whether --with-md5-passwords was given.
if test "${with_md5_passwords+set}" = set; then :
withval=$with_md5_passwords;
if test "x$withval" != "xno" ; then
$as_echo "#define HAVE_MD5_PASSWORDS 1" >>confdefs.h
MD5_MSG="yes"
fi
fi
# Whether to disable shadow password support
# Check whether --with-shadow was given.
if test "${with_shadow+set}" = set; then :
withval=$with_shadow;
if test "x$withval" = "xno" ; then
$as_echo "#define DISABLE_SHADOW 1" >>confdefs.h
disable_shadow=yes
fi
fi
if test -z "$disable_shadow" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the systems has expire shadow information" >&5
$as_echo_n "checking if the systems has expire shadow information... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <shadow.h>
struct spwd sp;
int
main ()
{
sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
sp_expire_available=yes
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "x$sp_expire_available" = "xyes" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAS_SHADOW_EXPIRE 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
fi
# Use ip address instead of hostname in $DISPLAY
if test ! -z "$IPADDR_IN_DISPLAY" ; then
DISPLAY_HACK_MSG="yes"
$as_echo "#define IPADDR_IN_DISPLAY 1" >>confdefs.h
else
DISPLAY_HACK_MSG="no"
# Check whether --with-ipaddr-display was given.
if test "${with_ipaddr_display+set}" = set; then :
withval=$with_ipaddr_display;
if test "x$withval" != "xno" ; then
$as_echo "#define IPADDR_IN_DISPLAY 1" >>confdefs.h
DISPLAY_HACK_MSG="yes"
fi
fi
fi
# check for /etc/default/login and use it if present.
# Check whether --enable-etc-default-login was given.
if test "${enable_etc_default_login+set}" = set; then :
enableval=$enable_etc_default_login; if test "x$enableval" = "xno"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: /etc/default/login handling disabled" >&5
$as_echo "$as_me: /etc/default/login handling disabled" >&6;}
etc_default_login=no
else
etc_default_login=yes
fi
else
if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes";
then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking /etc/default/login" >&5
$as_echo "$as_me: WARNING: cross compiling: not checking /etc/default/login" >&2;}
etc_default_login=no
else
etc_default_login=yes
fi
fi
if test "x$etc_default_login" != "xno"; then
as_ac_File=`$as_echo "ac_cv_file_"/etc/default/login"" | $as_tr_sh`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for \"/etc/default/login\"" >&5
$as_echo_n "checking for \"/etc/default/login\"... " >&6; }
if eval \${$as_ac_File+:} false; then :
$as_echo_n "(cached) " >&6
else
test "$cross_compiling" = yes &&
as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
if test -r ""/etc/default/login""; then
eval "$as_ac_File=yes"
else
eval "$as_ac_File=no"
fi
fi
eval ac_res=\$$as_ac_File
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
if eval test \"x\$"$as_ac_File"\" = x"yes"; then :
external_path_file=/etc/default/login
fi
if test "x$external_path_file" = "x/etc/default/login"; then
$as_echo "#define HAVE_ETC_DEFAULT_LOGIN 1" >>confdefs.h
fi
fi
if test $ac_cv_func_login_getcapbool = "yes" && \
test $ac_cv_header_login_cap_h = "yes" ; then
external_path_file=/etc/login.conf
fi
# Whether to mess with the default path
SERVER_PATH_MSG="(default)"
# Check whether --with-default-path was given.
if test "${with_default_path+set}" = set; then :
withval=$with_default_path;
if test "x$external_path_file" = "x/etc/login.conf" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
--with-default-path=PATH has no effect on this system.
Edit /etc/login.conf instead." >&5
$as_echo "$as_me: WARNING:
--with-default-path=PATH has no effect on this system.
Edit /etc/login.conf instead." >&2;}
elif test "x$withval" != "xno" ; then
if test ! -z "$external_path_file" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
--with-default-path=PATH will only be used if PATH is not defined in
$external_path_file ." >&5
$as_echo "$as_me: WARNING:
--with-default-path=PATH will only be used if PATH is not defined in
$external_path_file ." >&2;}
fi
user_path="$withval"
SERVER_PATH_MSG="$withval"
fi
else
if test "x$external_path_file" = "x/etc/login.conf" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Make sure the path to scp is in /etc/login.conf" >&5
$as_echo "$as_me: WARNING: Make sure the path to scp is in /etc/login.conf" >&2;}
else
if test ! -z "$external_path_file" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
If PATH is defined in $external_path_file, ensure the path to scp is included,
otherwise scp will not work." >&5
$as_echo "$as_me: WARNING:
If PATH is defined in $external_path_file, ensure the path to scp is included,
otherwise scp will not work." >&2;}
fi
if test "$cross_compiling" = yes; then :
user_path="/usr/bin:/bin:/usr/sbin:/sbin"
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* find out what STDPATH is */
#include <stdio.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#ifndef _PATH_STDPATH
# ifdef _PATH_USERPATH /* Irix */
# define _PATH_STDPATH _PATH_USERPATH
# else
# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
# endif
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DATA "conftest.stdpath"
int
main ()
{
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0)
exit(1);
exit(0);
;
return 0;
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
user_path=`cat conftest.stdpath`
else
user_path="/usr/bin:/bin:/usr/sbin:/sbin"
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
# make sure $bindir is in USER_PATH so scp will work
t_bindir="${bindir}"
while echo "${t_bindir}" | egrep '\$\{|NONE/' >/dev/null 2>&1; do
t_bindir=`eval echo ${t_bindir}`
case $t_bindir in
NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;;
esac
case $t_bindir in
NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;;
esac
done
echo $user_path | grep ":$t_bindir" > /dev/null 2>&1
if test $? -ne 0 ; then
echo $user_path | grep "^$t_bindir" > /dev/null 2>&1
if test $? -ne 0 ; then
user_path=$user_path:$t_bindir
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Adding $t_bindir to USER_PATH so scp will work" >&5
$as_echo "Adding $t_bindir to USER_PATH so scp will work" >&6; }
fi
fi
fi
fi
if test "x$external_path_file" != "x/etc/login.conf" ; then
cat >>confdefs.h <<_ACEOF
#define USER_PATH "$user_path"
_ACEOF
fi
# Set superuser path separately to user path
# Check whether --with-superuser-path was given.
if test "${with_superuser_path+set}" = set; then :
withval=$with_superuser_path;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
cat >>confdefs.h <<_ACEOF
#define SUPERUSER_PATH "$withval"
_ACEOF
superuser_path=$withval
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we need to convert IPv4 in IPv6-mapped addresses" >&5
$as_echo_n "checking if we need to convert IPv4 in IPv6-mapped addresses... " >&6; }
IPV4_IN6_HACK_MSG="no"
# Check whether --with-4in6 was given.
if test "${with_4in6+set}" = set; then :
withval=$with_4in6;
if test "x$withval" != "xno" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define IPV4_IN_IPV6 1" >>confdefs.h
IPV4_IN6_HACK_MSG="yes"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
else
if test "x$inet6_default_4in6" = "xyes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5
$as_echo "yes (default)" >&6; }
$as_echo "#define IPV4_IN_IPV6 1" >>confdefs.h
IPV4_IN6_HACK_MSG="yes"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no (default)" >&5
$as_echo "no (default)" >&6; }
fi
fi
# Whether to enable BSD auth support
BSD_AUTH_MSG=no
# Check whether --with-bsd-auth was given.
if test "${with_bsd_auth+set}" = set; then :
withval=$with_bsd_auth;
if test "x$withval" != "xno" ; then
$as_echo "#define BSD_AUTH 1" >>confdefs.h
BSD_AUTH_MSG=yes
fi
fi
# Where to place sshd.pid
piddir=/var/run
# make sure the directory exists
if test ! -d $piddir ; then
piddir=`eval echo ${sysconfdir}`
case $piddir in
NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;;
esac
fi
# Check whether --with-pid-dir was given.
if test "${with_pid_dir+set}" = set; then :
withval=$with_pid_dir;
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
piddir=$withval
if test ! -d $piddir ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** no $piddir directory on this system **" >&5
$as_echo "$as_me: WARNING: ** no $piddir directory on this system **" >&2;}
fi
fi
fi
cat >>confdefs.h <<_ACEOF
#define _PATH_SSH_PIDDIR "$piddir"
_ACEOF
# Check whether --enable-lastlog was given.
if test "${enable_lastlog+set}" = set; then :
enableval=$enable_lastlog;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
fi
fi
# Check whether --enable-utmp was given.
if test "${enable_utmp+set}" = set; then :
enableval=$enable_utmp;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
fi
fi
# Check whether --enable-utmpx was given.
if test "${enable_utmpx+set}" = set; then :
enableval=$enable_utmpx;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_UTMPX 1" >>confdefs.h
fi
fi
# Check whether --enable-wtmp was given.
if test "${enable_wtmp+set}" = set; then :
enableval=$enable_wtmp;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_WTMP 1" >>confdefs.h
fi
fi
# Check whether --enable-wtmpx was given.
if test "${enable_wtmpx+set}" = set; then :
enableval=$enable_wtmpx;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_WTMPX 1" >>confdefs.h
fi
fi
# Check whether --enable-libutil was given.
if test "${enable_libutil+set}" = set; then :
enableval=$enable_libutil;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_LOGIN 1" >>confdefs.h
fi
fi
# Check whether --enable-pututline was given.
if test "${enable_pututline+set}" = set; then :
enableval=$enable_pututline;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_PUTUTLINE 1" >>confdefs.h
fi
fi
# Check whether --enable-pututxline was given.
if test "${enable_pututxline+set}" = set; then :
enableval=$enable_pututxline;
if test "x$enableval" = "xno" ; then
$as_echo "#define DISABLE_PUTUTXLINE 1" >>confdefs.h
fi
fi
# Check whether --with-lastlog was given.
if test "${with_lastlog+set}" = set; then :
withval=$with_lastlog;
if test "x$withval" = "xno" ; then
$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
elif test -n "$withval" && test "x${withval}" != "xyes"; then
conf_lastlog_location=$withval
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines LASTLOG_FILE" >&5
$as_echo_n "checking if your system defines LASTLOG_FILE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_LASTLOG_H
# include <lastlog.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#ifdef HAVE_LOGIN_H
# include <login.h>
#endif
int
main ()
{
char *lastlog = LASTLOG_FILE;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines _PATH_LASTLOG" >&5
$as_echo_n "checking if your system defines _PATH_LASTLOG... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_LASTLOG_H
# include <lastlog.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
int
main ()
{
char *lastlog = _PATH_LASTLOG;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
system_lastlog_path=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test -z "$conf_lastlog_location"; then
if test x"$system_lastlog_path" = x"no" ; then
for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do
if (test -d "$f" || test -f "$f") ; then
conf_lastlog_location=$f
fi
done
if test -z "$conf_lastlog_location"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ** Cannot find lastlog **" >&5
$as_echo "$as_me: WARNING: ** Cannot find lastlog **" >&2;}
fi
fi
fi
if test -n "$conf_lastlog_location"; then
cat >>confdefs.h <<_ACEOF
#define CONF_LASTLOG_FILE "$conf_lastlog_location"
_ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines UTMP_FILE" >&5
$as_echo_n "checking if your system defines UTMP_FILE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
int
main ()
{
char *utmp = UTMP_FILE;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
system_utmp_path=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test -z "$conf_utmp_location"; then
if test x"$system_utmp_path" = x"no" ; then
for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do
if test -f $f ; then
conf_utmp_location=$f
fi
done
if test -z "$conf_utmp_location"; then
$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
fi
fi
fi
if test -n "$conf_utmp_location"; then
cat >>confdefs.h <<_ACEOF
#define CONF_UTMP_FILE "$conf_utmp_location"
_ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMP_FILE" >&5
$as_echo_n "checking if your system defines WTMP_FILE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
int
main ()
{
char *wtmp = WTMP_FILE;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
system_wtmp_path=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test -z "$conf_wtmp_location"; then
if test x"$system_wtmp_path" = x"no" ; then
for f in /usr/adm/wtmp /var/log/wtmp; do
if test -f $f ; then
conf_wtmp_location=$f
fi
done
if test -z "$conf_wtmp_location"; then
$as_echo "#define DISABLE_WTMP 1" >>confdefs.h
fi
fi
fi
if test -n "$conf_wtmp_location"; then
cat >>confdefs.h <<_ACEOF
#define CONF_WTMP_FILE "$conf_wtmp_location"
_ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if your system defines WTMPX_FILE" >&5
$as_echo_n "checking if your system defines WTMPX_FILE... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
int
main ()
{
char *wtmpx = WTMPX_FILE;
;
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
system_wtmpx_path=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test -z "$conf_wtmpx_location"; then
if test x"$system_wtmpx_path" = x"no" ; then
$as_echo "#define DISABLE_WTMPX 1" >>confdefs.h
fi
else
cat >>confdefs.h <<_ACEOF
#define CONF_WTMPX_FILE "$conf_wtmpx_location"
_ACEOF
fi
if test ! -z "$blibpath" ; then
LDFLAGS="$LDFLAGS $blibflags$blibpath"
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&5
$as_echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;}
fi
ac_fn_c_check_member "$LINENO" "struct lastlog" "ll_line" "ac_cv_member_struct_lastlog_ll_line" "
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UTMP_H
#include <utmp.h>
#endif
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
#ifdef HAVE_LASTLOG_H
#include <lastlog.h>
#endif
"
if test "x$ac_cv_member_struct_lastlog_ll_line" = xyes; then :
else
if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then
$as_echo "#define DISABLE_LASTLOG 1" >>confdefs.h
fi
fi
ac_fn_c_check_member "$LINENO" "struct utmp" "ut_line" "ac_cv_member_struct_utmp_ut_line" "
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UTMP_H
#include <utmp.h>
#endif
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
#ifdef HAVE_LASTLOG_H
#include <lastlog.h>
#endif
"
if test "x$ac_cv_member_struct_utmp_ut_line" = xyes; then :
else
$as_echo "#define DISABLE_UTMP 1" >>confdefs.h
$as_echo "#define DISABLE_WTMP 1" >>confdefs.h
fi
CFLAGS="$CFLAGS $werror_flags"
if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
TEST_SSH_IPV6=no
else
TEST_SSH_IPV6=yes
fi
ac_fn_c_check_decl "$LINENO" "BROKEN_GETADDRINFO" "ac_cv_have_decl_BROKEN_GETADDRINFO" "$ac_includes_default"
if test "x$ac_cv_have_decl_BROKEN_GETADDRINFO" = xyes; then :
TEST_SSH_IPV6=no
fi
TEST_SSH_IPV6=$TEST_SSH_IPV6
TEST_SSH_UTF8=$TEST_SSH_UTF8
TEST_MALLOC_OPTIONS=$TEST_MALLOC_OPTIONS
UNSUPPORTED_ALGORITHMS=$unsupported_algorithms
DEPEND=$(cat $srcdir/.depend)
CFLAGS="${CFLAGS} ${CFLAGS_AFTER}"
LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}"
ac_config_files="$ac_config_files Makefile buildpkg.sh opensshd.init openssh.xml openbsd-compat/Makefile openbsd-compat/regress/Makefile survey.sh"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems. If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# following values.
_ACEOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
*_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space=' '; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
# `set' does not quote correctly, so add quotes: double-quote
# substitution turns \\\\ into \\, and sed turns \\ into \.
sed -n \
"s/'/'\\\\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
;; #(
*)
# `set' quotes correctly as required by POSIX, so do not add quotes.
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
) |
sed '
/^ac_cv_env_/b end
t clear
:clear
s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
$as_echo "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
case $cache_file in #(
*/* | ?:*)
mv -f confcache "$cache_file"$$ &&
mv -f "$cache_file"$$ "$cache_file" ;; #(
*)
mv -f confcache "$cache_file" ;;
esac
fi
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
debug=false
ac_cs_recheck=false
ac_cs_silent=false
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
as_nl='
'
export as_nl
# Printing a long string crashes Solaris 7 /usr/bin/printf.
as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
# Prefer a ksh shell builtin over an external printf program on Solaris,
# but without wasting forks for bash or zsh.
if test -z "$BASH_VERSION$ZSH_VERSION" \
&& (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='print -r --'
as_echo_n='print -rn --'
elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
as_echo='printf %s\n'
as_echo_n='printf %s'
else
if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
as_echo_n='/usr/ucb/echo -n'
else
as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
as_echo_n_body='eval
arg=$1;
case $arg in #(
*"$as_nl"*)
expr "X$arg" : "X\\(.*\\)$as_nl";
arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
esac;
expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
'
export as_echo_n_body
as_echo_n='sh -c $as_echo_n_body as_echo'
fi
export as_echo_body
as_echo='sh -c $as_echo_body as_echo'
fi
# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
# IFS
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent editors from complaining about space-tab.
# (If _AS_PATH_WALK were called with IFS unset, it would disable word
# splitting by setting IFS to empty value.)
IFS=" "" $as_nl"
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
$as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
# Unset variables that we do not need and which cause bugs (e.g. in
# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
# suppresses any "Segmentation fault" message there. '((' could
# trigger a bug in pdksh 5.2.14.
for as_var in BASH_ENV ENV MAIL MAILPATH
do eval test x\${$as_var+set} = xset \
&& ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
done
PS1='$ '
PS2='> '
PS4='+ '
# NLS nuisances.
LC_ALL=C
export LC_ALL
LANGUAGE=C
export LANGUAGE
# CDPATH.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
$as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
$as_echo "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
else
as_fn_append ()
{
eval $1=\$$1\$2
}
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
else
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
*\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by OpenSSH $as_me Portable, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
CONFIG_LINKS = $CONFIG_LINKS
CONFIG_COMMANDS = $CONFIG_COMMANDS
$ $0 $@
on `(hostname || uname -n) 2>/dev/null | sed 1q`
"
_ACEOF
case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac
case $ac_config_headers in *"
"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
esac
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"
config_headers="$ac_config_headers"
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
from templates according to the current configuration. Unless the files
and actions are specified as TAGs, all are instantiated by default.
Usage: $0 [OPTION]... [TAG]...
-h, --help print this help, then exit
-V, --version print version number and configuration settings, then exit
--config print configuration, then exit
-q, --quiet, --silent
do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
--file=FILE[:TEMPLATE]
instantiate the configuration file FILE
--header=FILE[:TEMPLATE]
instantiate the configuration header FILE
Configuration files:
$config_files
Configuration headers:
$config_headers
Report bugs to <openssh-unix-dev@mindrot.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
OpenSSH config.status Portable
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
Copyright (C) 2012 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
ac_pwd='$ac_pwd'
srcdir='$srcdir'
INSTALL='$INSTALL'
MKDIR_P='$MKDIR_P'
AWK='$AWK'
test -n "\$AWK" || AWK=awk
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
case $1 in
--*=?*)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
--*=)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=
ac_shift=:
;;
*)
ac_option=$1
ac_optarg=$2
ac_shift=shift
;;
esac
case $ac_option in
# Handling of the options.
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
$as_echo "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
$as_echo "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
*\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
as_fn_error $? "ambiguous option: \`$1'
Try \`$0 --help' for more information.";;
--help | --hel | -h )
$as_echo "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
# This is an error.
-*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
*) as_fn_append ac_config_targets " $1"
ac_need_defaults=false ;;
esac
shift
done
ac_configure_extra_args=
if $ac_cs_silent; then
exec 6>/dev/null
ac_configure_extra_args="$ac_configure_extra_args --silent"
fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
\$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
fi
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
echo
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
$as_echo "$ac_log"
} >&5
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Handling of arguments.
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"buildpkg.sh") CONFIG_FILES="$CONFIG_FILES buildpkg.sh" ;;
"opensshd.init") CONFIG_FILES="$CONFIG_FILES opensshd.init" ;;
"openssh.xml") CONFIG_FILES="$CONFIG_FILES openssh.xml" ;;
"openbsd-compat/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/Makefile" ;;
"openbsd-compat/regress/Makefile") CONFIG_FILES="$CONFIG_FILES openbsd-compat/regress/Makefile" ;;
"survey.sh") CONFIG_FILES="$CONFIG_FILES survey.sh" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
done
# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used. Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
fi
# Have a temporary directory for convenience. Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
tmp= ac_tmp=
trap 'exit_status=$?
: "${ac_tmp:=$tmp}"
{ test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.
{
tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
test -d "$tmp"
} ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
if test -n "$CONFIG_FILES"; then
ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
ac_cs_awk_cr='\\r'
else
ac_cs_awk_cr=$ac_cr
fi
echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF
{
echo "cat >conf$$subs.awk <<_ACEOF" &&
echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
echo "_ACEOF"
} >conf$$subs.sh ||
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
. ./conf$$subs.sh ||
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
if test $ac_delim_n = $ac_delim_num; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
rm -f conf$$subs.sh
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s/'"$ac_delim"'$//
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t delim
' <conf$$subs.awk | sed '
/^[^""]/{
N
s/\n//
}
' >>$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
for (key in S) S_is_set[key] = 1
FS = ""
}
{
line = $ 0
nfields = split(line, field, "@")
substed = 0
len = length(field[1])
for (i = 2; i < nfields; i++) {
key = field[i]
keylen = length(key)
if (S_is_set[key]) {
value = S[key]
line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
len += length(value) + length(field[++i])
substed = 1
} else
len += 1 + keylen
}
print line
}
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
|| as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
h
s///
s/^/:/
s/[ ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
x
s/\(=[ ]*\).*/\1/
G
s/\n//
s/^[^=]*=[ ]*$//
}'
fi
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"
# Set up the scripts for CONFIG_HEADERS section.
# No need to generate them if there are no CONFIG_HEADERS.
# This happens for instance with `./config.status Makefile'.
if test -n "$CONFIG_HEADERS"; then
cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
BEGIN {
_ACEOF
# Transform confdefs.h into an awk script `defines.awk', embedded as
# here-document in config.status, that substitutes the proper values into
# config.h.in to produce config.h.
# Create a delimiter string that does not exist in confdefs.h, to ease
# handling of long lines.
ac_delim='%!_!# '
for ac_last_try in false false :; do
ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
if test -z "$ac_tt"; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
# For the awk script, D is an array of macro values keyed by name,
# likewise P contains macro parameters if any. Preserve backslash
# newline sequences.
ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
sed -n '
s/.\{148\}/&'"$ac_delim"'/g
t rset
:rset
s/^[ ]*#[ ]*define[ ][ ]*/ /
t def
d
:def
s/\\$//
t bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3"/p
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
d
:bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3\\\\\\n"\\/p
t cont
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
t cont
d
:cont
n
s/.\{148\}/&'"$ac_delim"'/g
t clear
:clear
s/\\$//
t bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/"/p
d
:bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
b cont
' <confdefs.h | sed '
s/'"$ac_delim"'/"\\\
"/g' >>$CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
for (key in D) D_is_set[key] = 1
FS = ""
}
/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
line = \$ 0
split(line, arg, " ")
if (arg[1] == "#") {
defundef = arg[2]
mac1 = arg[3]
} else {
defundef = substr(arg[1], 2)
mac1 = arg[2]
}
split(mac1, mac2, "(") #)
macro = mac2[1]
prefix = substr(line, 1, index(line, defundef) - 1)
if (D_is_set[macro]) {
# Preserve the white space surrounding the "#".
print prefix "define", macro P[macro] D[macro]
next
} else {
# Replace #undef with comments. This is necessary, for example,
# in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
if (defundef == "undef") {
print "/*", prefix defundef, macro, "*/"
next
}
}
}
{ print }
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
fi # test -n "$CONFIG_HEADERS"
eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
shift
for ac_tag
do
case $ac_tag in
:[FHLC]) ac_mode=$ac_tag; continue;;
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
ac_save_IFS=$IFS
IFS=:
set x $ac_tag
IFS=$ac_save_IFS
shift
ac_file=$1
shift
case $ac_mode in
:L) ac_source=$1;;
:[FH])
ac_file_inputs=
for ac_f
do
case $ac_f in
-) ac_f="$ac_tmp/stdin";;
*) # Look for the file first in the build tree, then in the source tree
# (if the path is not absolute). The absolute path cannot be DOS-style,
# because $ac_f cannot contain `:'.
test -f "$ac_f" ||
case $ac_f in
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
# Let's still pretend it is `configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
$as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
$as_echo "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
ac_sed_conf_input=`$as_echo "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
case $ac_tag in
*:-:* | *:-) cat >"$ac_tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
$as_echo X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
as_dir="$ac_dir"; as_fn_mkdir_p
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
case $ac_mode in
:F)
#
# CONFIG_FILE
#
case $INSTALL in
[\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
*) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
esac
ac_MKDIR_P=$MKDIR_P
case $MKDIR_P in
[\\/$]* | ?:[\\/]* ) ;;
*/*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
esac
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
p
q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
s&@datadir@&$datadir&g
s&@docdir@&$docdir&g
s&@infodir@&$infodir&g
s&@localedir@&$localedir&g
s&@mandir@&$mandir&g
s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF
# Neutralize VPATH when `$srcdir' = `.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
s&@INSTALL@&$ac_INSTALL&;t t
s&@MKDIR_P@&$ac_MKDIR_P&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
>$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
case $ac_file in
-) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
*) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
esac \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
:H)
#
# CONFIG_HEADER
#
if test x"$ac_file" != x-; then
{
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
} >"$ac_tmp/config.h" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
$as_echo "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$ac_tmp/config.h" "$ac_file" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
$as_echo "/* $configure_input */" \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
|| as_fn_error $? "could not create -" "$LINENO" 5
fi
;;
esac
done # for ac_tag
as_fn_exit 0
_ACEOF
ac_clean_files=$ac_clean_files_save
test $ac_write_fail = 0 ||
as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded. So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status. When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
ac_cs_success=:
ac_config_status_args=
test "$silent" = yes &&
ac_config_status_args="$ac_config_status_args --quiet"
exec 5>/dev/null
$SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
# Print summary of options
# Someone please show me a better way :)
A=`eval echo ${prefix}` ; A=`eval echo ${A}`
B=`eval echo ${bindir}` ; B=`eval echo ${B}`
C=`eval echo ${sbindir}` ; C=`eval echo ${C}`
D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}`
E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}`
F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}`
G=`eval echo ${piddir}` ; G=`eval echo ${G}`
H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}`
I=`eval echo ${user_path}` ; I=`eval echo ${I}`
J=`eval echo ${superuser_path}` ; J=`eval echo ${J}`
echo ""
echo "OpenSSH has been configured with the following options:"
echo " User binaries: $B"
echo " System binaries: $C"
echo " Configuration files: $D"
echo " Askpass program: $E"
echo " Manual pages: $F"
echo " PID file: $G"
echo " Privilege separation chroot path: $H"
if test "x$external_path_file" = "x/etc/login.conf" ; then
echo " At runtime, sshd will use the path defined in $external_path_file"
echo " Make sure the path to scp is present, otherwise scp will not work"
else
echo " sshd default user PATH: $I"
if test ! -z "$external_path_file"; then
echo " (If PATH is set in $external_path_file it will be used instead. If"
echo " used, ensure the path to scp is present, otherwise scp will not work.)"
fi
fi
if test ! -z "$superuser_path" ; then
echo " sshd superuser user PATH: $J"
fi
echo " Manpage format: $MANTYPE"
echo " PAM support: $PAM_MSG"
echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG"
echo " SELinux support: $SELINUX_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " libldns support: $LDNS_MSG"
echo " Solaris process contract support: $SPC_MSG"
echo " Solaris project support: $SP_MSG"
echo " Solaris privilege support: $SPP_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
echo ""
echo " Host: ${host}"
echo " Compiler: ${CC}"
echo " Compiler flags: ${CFLAGS}"
echo "Preprocessor flags: ${CPPFLAGS}"
echo " Linker flags: ${LDFLAGS}"
echo " Libraries: ${LIBS}"
if test ! -z "${SSHDLIBS}"; then
echo " +for sshd: ${SSHDLIBS}"
fi
if test ! -z "${SSHLIBS}"; then
echo " +for ssh: ${SSHLIBS}"
fi
echo ""
if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then
echo "SVR4 style packages are supported with \"make package\""
echo ""
fi
if test "x$PAM_MSG" = "xyes" ; then
echo "PAM is enabled. You may need to install a PAM control file "
echo "for sshd, otherwise password authentication may fail. "
echo "Example PAM control files can be found in the contrib/ "
echo "subdirectory"
echo ""
fi
if test ! -z "$NO_PEERCHECK" ; then
echo "WARNING: the operating system that you are using does not"
echo "appear to support getpeereid(), getpeerucred() or the"
echo "SO_PEERCRED getsockopt() option. These facilities are used to"
echo "enforce security checks to prevent unauthorised connections to"
echo "ssh-agent. Their absence increases the risk that a malicious"
echo "user can connect to your agent."
echo ""
fi
if test "$AUDIT_MODULE" = "bsm" ; then
echo "WARNING: BSM audit support is currently considered EXPERIMENTAL."
echo "See the Solaris section in README.platform for details."
fi
diff --git a/configure.ac b/configure.ac
index 7379ab3589e1..30be6c18266d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5363 +1,5303 @@
#
# Copyright (c) 1999-2004 Damien Miller
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
AC_REVISION($Revision: 1.583 $)
AC_CONFIG_SRCDIR([ssh.c])
AC_LANG([C])
AC_CONFIG_HEADER([config.h])
-AC_PROG_CC
+AC_PROG_CC([cc gcc])
AC_CANONICAL_HOST
AC_C_BIGENDIAN
# Checks for programs.
AC_PROG_AWK
AC_PROG_CPP
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_EGREP
AC_PROG_MKDIR_P
AC_CHECK_TOOLS([AR], [ar])
AC_PATH_PROG([CAT], [cat])
AC_PATH_PROG([KILL], [kill])
AC_PATH_PROG([SED], [sed])
AC_PATH_PROG([ENT], [ent])
AC_SUBST([ENT])
AC_PATH_PROG([TEST_MINUS_S_SH], [bash])
AC_PATH_PROG([TEST_MINUS_S_SH], [ksh])
AC_PATH_PROG([TEST_MINUS_S_SH], [sh])
AC_PATH_PROG([SH], [sh])
AC_PATH_PROG([GROFF], [groff])
AC_PATH_PROG([NROFF], [nroff])
AC_PATH_PROG([MANDOC], [mandoc])
AC_SUBST([TEST_SHELL], [sh])
dnl select manpage formatter
if test "x$MANDOC" != "x" ; then
MANFMT="$MANDOC"
elif test "x$NROFF" != "x" ; then
MANFMT="$NROFF -mandoc"
elif test "x$GROFF" != "x" ; then
MANFMT="$GROFF -mandoc -Tascii"
else
AC_MSG_WARN([no manpage formatted found])
MANFMT="false"
fi
AC_SUBST([MANFMT])
dnl for buildpkg.sh
AC_PATH_PROG([PATH_GROUPADD_PROG], [groupadd], [groupadd],
[/usr/sbin${PATH_SEPARATOR}/etc])
AC_PATH_PROG([PATH_USERADD_PROG], [useradd], [useradd],
[/usr/sbin${PATH_SEPARATOR}/etc])
AC_CHECK_PROG([MAKE_PACKAGE_SUPPORTED], [pkgmk], [yes], [no])
if test -x /sbin/sh; then
AC_SUBST([STARTUP_SCRIPT_SHELL], [/sbin/sh])
else
AC_SUBST([STARTUP_SCRIPT_SHELL], [/bin/sh])
fi
# System features
AC_SYS_LARGEFILE
if test -z "$AR" ; then
AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***])
fi
AC_PATH_PROG([PATH_PASSWD_PROG], [passwd])
if test ! -z "$PATH_PASSWD_PROG" ; then
AC_DEFINE_UNQUOTED([_PATH_PASSWD_PROG], ["$PATH_PASSWD_PROG"],
[Full path of your "passwd" program])
fi
dnl Since autoconf doesn't support it very well, we no longer allow users to
dnl override LD, however keeping the hook here for now in case there's a use
dnl use case we overlooked and someone needs to re-enable it. Unless a good
dnl reason is found we'll be removing this in future.
LD="$CC"
AC_SUBST([LD])
AC_C_INLINE
AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include <limits.h>])
AC_CHECK_DECL([SYSTR_POLICY_KILL], [have_systr_policy_kill=1], , [
#include <sys/types.h>
#include <sys/param.h>
#include <dev/systrace.h>
])
AC_CHECK_DECL([RLIMIT_NPROC],
[AC_DEFINE([HAVE_RLIMIT_NPROC], [], [sys/resource.h has RLIMIT_NPROC])], , [
#include <sys/types.h>
#include <sys/resource.h>
])
AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [
#include <sys/types.h>
#include <linux/prctl.h>
])
openssl=yes
AC_ARG_WITH([openssl],
[ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ],
[ if test "x$withval" = "xno" ; then
openssl=no
fi
]
)
AC_MSG_CHECKING([whether OpenSSL will be used for cryptography])
if test "x$openssl" = "xyes" ; then
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography])
else
AC_MSG_RESULT([no])
fi
use_stack_protector=1
use_toolchain_hardening=1
AC_ARG_WITH([stackprotect],
[ --without-stackprotect Don't use compiler's stack protection], [
if test "x$withval" = "xno"; then
use_stack_protector=0
fi ])
AC_ARG_WITH([hardening],
[ --without-hardening Don't use toolchain hardening flags], [
if test "x$withval" = "xno"; then
use_toolchain_hardening=0
fi ])
# We use -Werror for the tests only so that we catch warnings like "this is
# on by default" for things like -fPIE.
AC_MSG_CHECKING([if $CC supports -Werror])
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])],
[ AC_MSG_RESULT([yes])
WERROR="-Werror"],
[ AC_MSG_RESULT([no])
WERROR="" ]
)
CFLAGS="$saved_CFLAGS"
if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
OSSH_CHECK_CFLAG_COMPILE([-pipe])
OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments])
OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option])
OSSH_CHECK_CFLAG_COMPILE([-Wall])
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith])
OSSH_CHECK_CFLAG_COMPILE([-Wuninitialized])
OSSH_CHECK_CFLAG_COMPILE([-Wsign-compare])
OSSH_CHECK_CFLAG_COMPILE([-Wformat-security])
OSSH_CHECK_CFLAG_COMPILE([-Wsizeof-pointer-memaccess])
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign])
OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result])
OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
if test "x$use_toolchain_hardening" = "x1"; then
OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt])
OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack])
# NB. -ftrapv expects certain support functions to be present in
# the compiler library (libgcc or similar) to detect integer operations
# that can overflow. We must check that the result of enabling it
# actually links. The test program compiled/linked includes a number
# of integer operations that should exercise this.
OSSH_CHECK_CFLAG_LINK([-ftrapv])
fi
AC_MSG_CHECKING([gcc version])
GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'`
case $GCC_VER in
1.*) no_attrib_nonnull=1 ;;
2.8* | 2.9*)
no_attrib_nonnull=1
;;
2.*) no_attrib_nonnull=1 ;;
*) ;;
esac
AC_MSG_RESULT([$GCC_VER])
AC_MSG_CHECKING([if $CC accepts -fno-builtin-memset])
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fno-builtin-memset"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <string.h> ]],
[[ char b[10]; memset(b, 0, sizeof(b)); ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
CFLAGS="$saved_CFLAGS" ]
)
# -fstack-protector-all doesn't always work for some GCC versions
# and/or platforms, so we test if we can. If it's not supported
# on a given platform gcc will emit a warning so we use -Werror.
if test "x$use_stack_protector" = "x1"; then
for t in -fstack-protector-strong -fstack-protector-all \
-fstack-protector; do
AC_MSG_CHECKING([if $CC supports $t])
saved_CFLAGS="$CFLAGS"
saved_LDFLAGS="$LDFLAGS"
CFLAGS="$CFLAGS $t -Werror"
LDFLAGS="$LDFLAGS $t -Werror"
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[
char x[256];
snprintf(x, sizeof(x), "XXX");
]])],
[ AC_MSG_RESULT([yes])
CFLAGS="$saved_CFLAGS $t"
LDFLAGS="$saved_LDFLAGS $t"
AC_MSG_CHECKING([if $t works])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[
char x[256];
snprintf(x, sizeof(x), "XXX");
]])],
[ AC_MSG_RESULT([yes])
break ],
[ AC_MSG_RESULT([no]) ],
[ AC_MSG_WARN([cross compiling: cannot test])
break ]
)
],
[ AC_MSG_RESULT([no]) ]
)
CFLAGS="$saved_CFLAGS"
LDFLAGS="$saved_LDFLAGS"
done
fi
if test -z "$have_llong_max"; then
# retry LLONG_MAX with -std=gnu99, needed on some Linuxes
unset ac_cv_have_decl_LLONG_MAX
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -std=gnu99"
AC_CHECK_DECL([LLONG_MAX],
[have_llong_max=1],
[CFLAGS="$saved_CFLAGS"],
[#include <limits.h>]
)
fi
fi
AC_MSG_CHECKING([if compiler allows __attribute__ on return types])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdlib.h>
__attribute__((__unused__)) static void foo(void){return;}]],
[[ exit(0); ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_DEFINE(NO_ATTRIBUTE_ON_RETURN_TYPE, 1,
[compiler does not accept __attribute__ on return types]) ]
)
AC_MSG_CHECKING([if compiler allows __attribute__ prototype args])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdlib.h>
typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]],
[[ exit(0); ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_DEFINE(NO_ATTRIBUTE_ON_PROTOTYPE_ARGS, 1,
[compiler does not accept __attribute__ on prototype args]) ]
)
if test "x$no_attrib_nonnull" != "x1" ; then
AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull])
fi
AC_ARG_WITH([rpath],
[ --without-rpath Disable auto-added -R linker paths],
[
if test "x$withval" = "xno" ; then
- need_dash_r=""
- fi
- if test "x$withval" = "xyes" ; then
- need_dash_r=1
+ rpath_opt=""
+ elif test "x$withval" = "xyes" ; then
+ rpath_opt="-R"
+ else
+ rpath_opt="$withval"
fi
]
)
# Allow user to specify flags
AC_ARG_WITH([cflags],
[ --with-cflags Specify additional flags to pass to compiler],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CFLAGS="$CFLAGS $withval"
fi
]
)
AC_ARG_WITH([cflags-after],
[ --with-cflags-after Specify additional flags to pass to compiler after configure],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CFLAGS_AFTER="$withval"
fi
]
)
AC_ARG_WITH([cppflags],
[ --with-cppflags Specify additional flags to pass to preprocessor] ,
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CPPFLAGS="$CPPFLAGS $withval"
fi
]
)
AC_ARG_WITH([ldflags],
[ --with-ldflags Specify additional flags to pass to linker],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LDFLAGS="$LDFLAGS $withval"
fi
]
)
AC_ARG_WITH([ldflags-after],
[ --with-ldflags-after Specify additional flags to pass to linker after configure],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LDFLAGS_AFTER="$withval"
fi
]
)
AC_ARG_WITH([libs],
[ --with-libs Specify additional libraries to link with],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LIBS="$LIBS $withval"
fi
]
)
AC_ARG_WITH([Werror],
[ --with-Werror Build main code with -Werror],
[
if test -n "$withval" && test "x$withval" != "xno"; then
werror_flags="-Werror"
if test "x${withval}" != "xyes"; then
werror_flags="$withval"
fi
fi
]
)
AC_CHECK_HEADERS([ \
blf.h \
bstring.h \
crypt.h \
crypto/sha2.h \
dirent.h \
endian.h \
elf.h \
err.h \
features.h \
fcntl.h \
floatingpoint.h \
getopt.h \
glob.h \
ia.h \
iaf.h \
ifaddrs.h \
inttypes.h \
langinfo.h \
limits.h \
locale.h \
login.h \
maillock.h \
ndir.h \
net/if_tun.h \
netdb.h \
netgroup.h \
pam/pam_appl.h \
paths.h \
poll.h \
pty.h \
readpassphrase.h \
rpc/types.h \
security/pam_appl.h \
sha2.h \
shadow.h \
stddef.h \
stdint.h \
string.h \
strings.h \
sys/bitypes.h \
sys/bsdtty.h \
sys/cdefs.h \
sys/dir.h \
sys/file.h \
sys/mman.h \
sys/label.h \
sys/ndir.h \
sys/poll.h \
sys/prctl.h \
sys/pstat.h \
sys/ptrace.h \
sys/random.h \
sys/select.h \
sys/stat.h \
sys/stream.h \
sys/stropts.h \
sys/strtio.h \
sys/statvfs.h \
sys/sysmacros.h \
sys/time.h \
sys/timers.h \
sys/vfs.h \
time.h \
tmpdir.h \
ttyent.h \
ucred.h \
unistd.h \
usersec.h \
util.h \
utime.h \
utmp.h \
utmpx.h \
vis.h \
wchar.h \
])
# On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h]
# to be included first.
AC_CHECK_HEADERS([sys/audit.h], [], [], [
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_LABEL_H
# include <sys/label.h>
#endif
])
# sys/capsicum.h requires sys/types.h
AC_CHECK_HEADERS([sys/capsicum.h], [], [], [
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
])
# net/route.h requires sys/socket.h and sys/types.h.
# sys/sysctl.h also requires sys/param.h
AC_CHECK_HEADERS([net/route.h sys/sysctl.h], [], [], [
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/socket.h>
])
# lastlog.h requires sys/time.h to be included first on Solaris
AC_CHECK_HEADERS([lastlog.h], [], [], [
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
])
# sys/ptms.h requires sys/stream.h to be included first on Solaris
AC_CHECK_HEADERS([sys/ptms.h], [], [], [
#ifdef HAVE_SYS_STREAM_H
# include <sys/stream.h>
#endif
])
# login_cap.h requires sys/types.h on NetBSD
AC_CHECK_HEADERS([login_cap.h], [], [], [
#include <sys/types.h>
])
# older BSDs need sys/param.h before sys/mount.h
AC_CHECK_HEADERS([sys/mount.h], [], [], [
#include <sys/param.h>
])
# Android requires sys/socket.h to be included before sys/un.h
AC_CHECK_HEADERS([sys/un.h], [], [], [
#include <sys/types.h>
#include <sys/socket.h>
])
# Messages for features tested for in target-specific section
SIA_MSG="no"
SPC_MSG="no"
SP_MSG="no"
SPP_MSG="no"
# Support for Solaris/Illumos privileges (this test is used by both
# the --with-solaris-privs option and --with-sandbox=solaris).
SOLARIS_PRIVS="no"
# Check for some target-specific stuff
case "$host" in
*-*-aix*)
# Some versions of VAC won't allow macro redefinitions at
# -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that
# particularly with older versions of vac or xlc.
# It also throws errors about null macro arguments, but these are
# not fatal.
AC_MSG_CHECKING([if compiler allows macro redefinitions])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[
#define testmacro foo
#define testmacro bar]],
[[ exit(0); ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`"
CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`"
CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`"
]
)
AC_MSG_CHECKING([how to specify blibpath for linker ($LD)])
if (test -z "$blibpath"); then
blibpath="/usr/lib:/lib"
fi
saved_LDFLAGS="$LDFLAGS"
if test "$GCC" = "yes"; then
flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:"
else
flags="-blibpath: -Wl,-blibpath: -Wl,-rpath,"
fi
for tryflags in $flags ;do
if (test -z "$blibflags"); then
LDFLAGS="$saved_LDFLAGS $tryflags$blibpath"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[blibflags=$tryflags], [])
fi
done
if (test -z "$blibflags"); then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([*** must be able to specify blibpath on AIX - check config.log])
else
AC_MSG_RESULT([$blibflags])
fi
LDFLAGS="$saved_LDFLAGS"
dnl Check for authenticate. Might be in libs.a on older AIXes
AC_CHECK_FUNC([authenticate], [AC_DEFINE([WITH_AIXAUTHENTICATE], [1],
[Define if you want to enable AIX4's authenticate function])],
[AC_CHECK_LIB([s], [authenticate],
[ AC_DEFINE([WITH_AIXAUTHENTICATE])
LIBS="$LIBS -ls"
])
])
dnl Check for various auth function declarations in headers.
AC_CHECK_DECLS([authenticate, loginrestrictions, loginsuccess,
passwdexpired, setauthdb], , , [#include <usersec.h>])
dnl Check if loginfailed is declared and takes 4 arguments (AIX >= 5.2)
AC_CHECK_DECLS([loginfailed],
[AC_MSG_CHECKING([if loginfailed takes 4 arguments])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <usersec.h> ]],
[[ (void)loginfailed("user","host","tty",0); ]])],
[AC_MSG_RESULT([yes])
AC_DEFINE([AIX_LOGINFAILED_4ARG], [1],
[Define if your AIX loginfailed() function
takes 4 arguments (AIX >= 5.2)])], [AC_MSG_RESULT([no])
])],
[],
[#include <usersec.h>]
)
AC_CHECK_FUNCS([getgrset setauthdb])
AC_CHECK_DECL([F_CLOSEM],
AC_DEFINE([HAVE_FCNTL_CLOSEM], [1], [Use F_CLOSEM fcntl for closefrom]),
[],
[ #include <limits.h>
#include <fcntl.h> ]
)
check_for_aix_broken_getaddrinfo=1
AC_DEFINE([BROKEN_REALPATH], [1], [Define if you have a broken realpath.])
AC_DEFINE([SETEUID_BREAKS_SETUID], [1],
[Define if your platform breaks doing a seteuid before a setuid])
AC_DEFINE([BROKEN_SETREUID], [1], [Define if your setreuid() is broken])
AC_DEFINE([BROKEN_SETREGID], [1], [Define if your setregid() is broken])
dnl AIX handles lastlog as part of its login message
AC_DEFINE([DISABLE_LASTLOG], [1], [Define if you don't want to use lastlog])
AC_DEFINE([LOGIN_NEEDS_UTMPX], [1],
[Some systems need a utmpx entry for /bin/login to work])
AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV],
[Define to a Set Process Title type if your system is
supported by bsd-setproctitle.c])
AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1],
[AIX 5.2 and 5.3 (and presumably newer) require this])
AC_DEFINE([PTY_ZEROREAD], [1], [read(1) can return 0 for a non-closed fd])
AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)])
AC_DEFINE([BROKEN_STRNDUP], 1, [strndup broken, see APAR IY61211])
AC_DEFINE([BROKEN_STRNLEN], 1, [strnlen broken, see APAR IY62551])
;;
*-*-android*)
AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp])
AC_DEFINE([DISABLE_WTMP], [1], [Define if you don't want to use wtmp])
;;
*-*-cygwin*)
check_for_libcrypt_later=1
LIBS="$LIBS /usr/lib/textreadmode.o"
AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin])
AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()])
AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
[Define to disable UID restoration test])
AC_DEFINE([DISABLE_SHADOW], [1],
[Define if you want to disable shadow passwords])
AC_DEFINE([NO_X11_UNIX_SOCKETS], [1],
[Define if X11 doesn't support AF_UNIX sockets on that system])
AC_DEFINE([DISABLE_FD_PASSING], [1],
[Define if your platform needs to skip post auth
file descriptor passing])
AC_DEFINE([SSH_IOBUFSZ], [65535], [Windows is sensitive to read buffer size])
AC_DEFINE([FILESYSTEM_NO_BACKSLASH], [1], [File names may not contain backslash characters])
# Cygwin defines optargs, optargs as declspec(dllimport) for historical
# reasons which cause compile warnings, so we disable those warnings.
OSSH_CHECK_CFLAG_COMPILE([-Wno-attributes])
;;
*-*-dgux*)
AC_DEFINE([IP_TOS_IS_BROKEN], [1],
[Define if your system choked on IP TOS setting])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
;;
*-*-darwin*)
use_pie=auto
AC_MSG_CHECKING([if we have working getaddrinfo])
AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include <mach-o/dyld.h>
main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
exit(0);
else
exit(1);
}
]])],
[AC_MSG_RESULT([working])],
[AC_MSG_RESULT([buggy])
AC_DEFINE([BROKEN_GETADDRINFO], [1],
[getaddrinfo is broken (if present)])
],
[AC_MSG_RESULT([assume it is working])])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect])
AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1],
[Define if your resolver libs need this for getrrsetbyname])
AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
AC_DEFINE([SSH_TUN_COMPAT_AF], [1],
[Use tunnel device compatibility to OpenBSD])
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
m4_pattern_allow([AU_IPv])
AC_CHECK_DECL([AU_IPv4], [],
AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
[#include <bsm/audit.h>]
AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1],
[Define if pututxline updates lastlog too])
)
AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV],
[Define to a Set Process Title type if your system is
supported by bsd-setproctitle.c])
AC_CHECK_FUNCS([sandbox_init])
AC_CHECK_HEADERS([sandbox.h])
AC_CHECK_LIB([sandbox], [sandbox_apply], [
SSHDLIBS="$SSHDLIBS -lsandbox"
])
;;
*-*-dragonfly*)
SSHDLIBS="$SSHDLIBS -lcrypt"
TEST_MALLOC_OPTIONS="AFGJPRX"
;;
*-*-haiku*)
LIBS="$LIBS -lbsd "
AC_CHECK_LIB([network], [socket])
AC_DEFINE([HAVE_U_INT64_T])
MANTYPE=man
;;
*-*-hpux*)
# first we define all of the options common to all HP-UX releases
CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
IPADDR_IN_DISPLAY=yes
AC_DEFINE([USE_PIPES])
AC_DEFINE([LOGIN_NEEDS_UTMPX])
AC_DEFINE([LOCKED_PASSWD_STRING], ["*"],
[String used in /etc/passwd to denote locked account])
AC_DEFINE([SPT_TYPE], [SPT_PSTAT])
AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)])
maildir="/var/mail"
LIBS="$LIBS -lsec"
AC_CHECK_LIB([xnet], [t_error], ,
[AC_MSG_ERROR([*** -lxnet needed on HP-UX - check config.log ***])])
# next, we define all of the options specific to major releases
case "$host" in
*-*-hpux10*)
if test -z "$GCC"; then
CFLAGS="$CFLAGS -Ae"
fi
;;
*-*-hpux11*)
AC_DEFINE([PAM_SUN_CODEBASE], [1],
[Define if you are using Solaris-derived PAM which
passes pam_messages to the conversation function
with an extra level of indirection])
AC_DEFINE([DISABLE_UTMP], [1],
[Define if you don't want to use utmp])
AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins])
check_for_hpux_broken_getaddrinfo=1
check_for_conflicting_getspnam=1
;;
esac
# lastly, we define options specific to minor releases
case "$host" in
*-*-hpux10.26)
AC_DEFINE([HAVE_SECUREWARE], [1],
[Define if you have SecureWare-based
protected password database])
disable_ptmx_check=yes
LIBS="$LIBS -lsecpw"
;;
esac
;;
*-*-irix5*)
PATH="$PATH:/usr/etc"
AC_DEFINE([BROKEN_INET_NTOA], [1],
[Define if you system's inet_ntoa is busted
(e.g. Irix gcc issue)])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([WITH_ABBREV_NO_TTY], [1],
[Define if you shouldn't strip 'tty' from your
ttyname in [uw]tmp])
AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
;;
*-*-irix6*)
PATH="$PATH:/usr/etc"
AC_DEFINE([WITH_IRIX_ARRAY], [1],
[Define if you have/want arrays
(cluster-wide session management, not C arrays)])
AC_DEFINE([WITH_IRIX_PROJECT], [1],
[Define if you want IRIX project management])
AC_DEFINE([WITH_IRIX_AUDIT], [1],
[Define if you want IRIX audit trails])
AC_CHECK_FUNC([jlimit_startjob], [AC_DEFINE([WITH_IRIX_JOBS], [1],
[Define if you want IRIX kernel jobs])])
AC_DEFINE([BROKEN_INET_NTOA])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([BROKEN_UPDWTMPX], [1], [updwtmpx is broken (if present)])
AC_DEFINE([WITH_ABBREV_NO_TTY])
AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
;;
*-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
check_for_libcrypt_later=1
AC_DEFINE([PAM_TTY_KLUDGE])
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"])
AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV])
AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts])
AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins])
;;
*-*-linux*)
no_dev_ptmx=1
use_pie=auto
check_for_libcrypt_later=1
check_for_openpty_ctty_bug=1
dnl Target SUSv3/POSIX.1-2001 plus BSD specifics.
dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE
CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE"
AC_DEFINE([PAM_TTY_KLUDGE], [1],
[Work around problematic Linux PAM modules handling of PAM_TTY])
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"],
[String used in /etc/passwd to denote locked account])
AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV])
AC_DEFINE([LINK_OPNOTSUPP_ERRNO], [EPERM],
[Define to whatever link() returns for "not supported"
if it doesn't return EOPNOTSUPP.])
AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts])
AC_DEFINE([USE_BTMP])
AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer])
inet6_default_4in6=yes
case `uname -r` in
1.*|2.0.*)
AC_DEFINE([BROKEN_CMSG_TYPE], [1],
[Define if cmsg_type is not passed correctly])
;;
esac
# tun(4) forwarding compat code
AC_CHECK_HEADERS([linux/if_tun.h])
if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then
AC_DEFINE([SSH_TUN_LINUX], [1],
[Open tunnel devices the Linux tun/tap way])
AC_DEFINE([SSH_TUN_COMPAT_AF], [1],
[Use tunnel device compatibility to OpenBSD])
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
fi
AC_CHECK_HEADER([linux/if.h],
AC_DEFINE([SYS_RDOMAIN_LINUX], [1],
[Support routing domains using Linux VRF]), [], [
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.H>
#endif
])
AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h linux/audit.h], [],
[], [#include <linux/types.h>])
# Obtain MIPS ABI
case "$host" in
mips*)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if _MIPS_SIM != _ABIO32
#error
#endif
]])],[mips_abi="o32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if _MIPS_SIM != _ABIN32
#error
#endif
]])],[mips_abi="n32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#if _MIPS_SIM != _ABI64
#error
#endif
]])],[mips_abi="n64"],[AC_MSG_ERROR([unknown MIPS ABI])
])
])
])
;;
esac
AC_MSG_CHECKING([for seccomp architecture])
seccomp_audit_arch=
case "$host" in
x86_64-*)
seccomp_audit_arch=AUDIT_ARCH_X86_64
;;
i*86-*)
seccomp_audit_arch=AUDIT_ARCH_I386
;;
arm*-*)
seccomp_audit_arch=AUDIT_ARCH_ARM
;;
aarch64*-*)
seccomp_audit_arch=AUDIT_ARCH_AARCH64
;;
s390x-*)
seccomp_audit_arch=AUDIT_ARCH_S390X
;;
s390-*)
seccomp_audit_arch=AUDIT_ARCH_S390
;;
powerpc64-*)
seccomp_audit_arch=AUDIT_ARCH_PPC64
;;
powerpc64le-*)
seccomp_audit_arch=AUDIT_ARCH_PPC64LE
;;
mips-*)
seccomp_audit_arch=AUDIT_ARCH_MIPS
;;
mipsel-*)
seccomp_audit_arch=AUDIT_ARCH_MIPSEL
;;
mips64-*)
case "$mips_abi" in
"n32")
seccomp_audit_arch=AUDIT_ARCH_MIPS64N32
;;
"n64")
seccomp_audit_arch=AUDIT_ARCH_MIPS64
;;
esac
;;
mips64el-*)
case "$mips_abi" in
"n32")
seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32
;;
"n64")
seccomp_audit_arch=AUDIT_ARCH_MIPSEL64
;;
esac
;;
esac
if test "x$seccomp_audit_arch" != "x" ; then
AC_MSG_RESULT(["$seccomp_audit_arch"])
AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch],
[Specify the system call convention in use])
else
AC_MSG_RESULT([architecture not supported])
fi
;;
mips-sony-bsd|mips-sony-newsos4)
AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to acquire controlling tty])
SONY=1
;;
*-*-netbsd*)
check_for_libcrypt_before=1
if test "x$withval" != "xno" ; then
- need_dash_r=1
+ rpath_opt="-R"
fi
CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE"
AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
AC_CHECK_HEADER([net/if_tap.h], ,
AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support]))
AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
[Prepend the address family to IP tunnel traffic])
TEST_MALLOC_OPTIONS="AJRX"
AC_DEFINE([BROKEN_READ_COMPARISON], [1],
[NetBSD read function is sometimes redirected, breaking atomicio comparisons against it])
;;
*-*-freebsd*)
check_for_libcrypt_later=1
AC_DEFINE([LOCKED_PASSWD_PREFIX], ["*LOCKED*"], [Account locked with pw(1)])
AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way])
AC_CHECK_HEADER([net/if_tap.h], ,
AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support]))
AC_DEFINE([BROKEN_GLOB], [1], [FreeBSD glob does not do what we need])
TEST_MALLOC_OPTIONS="AJRX"
# Preauth crypto occasionally uses file descriptors for crypto offload
# and will crash if they cannot be opened.
AC_DEFINE([SANDBOX_SKIP_RLIMIT_NOFILE], [1],
[define if setrlimit RLIMIT_NOFILE breaks things])
;;
*-*-bsdi*)
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
;;
*-next-*)
conf_lastlog_location="/usr/adm/lastlog"
conf_utmp_location=/etc/utmp
conf_wtmp_location=/usr/adm/wtmp
maildir=/usr/spool/mail
AC_DEFINE([HAVE_NEXT], [1], [Define if you are on NeXT])
AC_DEFINE([BROKEN_REALPATH])
AC_DEFINE([USE_PIPES])
AC_DEFINE([BROKEN_SAVED_UIDS], [1], [Needed for NeXT])
;;
*-*-openbsd*)
use_pie=auto
AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], [OpenBSD's gcc has sentinel])
AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD's gcc has bounded])
AC_DEFINE([SSH_TUN_OPENBSD], [1], [Open tunnel devices the OpenBSD way])
AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1],
[syslog_r function is safe to use in in a signal handler])
TEST_MALLOC_OPTIONS="AFGJPRX"
;;
*-*-solaris*)
if test "x$withval" != "xno" ; then
- need_dash_r=1
+ rpath_opt="-R"
fi
AC_DEFINE([PAM_SUN_CODEBASE])
AC_DEFINE([LOGIN_NEEDS_UTMPX])
AC_DEFINE([PAM_TTY_KLUDGE])
AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1],
[Define if pam_chauthtok wants real uid set
to the unpriv'ed user])
AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
# Pushing STREAMS modules will cause sshd to acquire a controlling tty.
AC_DEFINE([SSHD_ACQUIRES_CTTY], [1],
[Define if sshd somehow reacquires a controlling TTY
after setsid()])
AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd
in case the name is longer than 8 chars])
AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1], [tcgetattr with ICANON may hang])
external_path_file=/etc/default/login
# hardwire lastlog location (can't detect it on some versions)
conf_lastlog_location="/var/adm/lastlog"
AC_MSG_CHECKING([for obsolete utmp and wtmp in solaris2.x])
sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'`
if test "$sol2ver" -ge 8; then
AC_MSG_RESULT([yes])
AC_DEFINE([DISABLE_UTMP])
AC_DEFINE([DISABLE_WTMP], [1],
[Define if you don't want to use wtmp])
else
AC_MSG_RESULT([no])
fi
AC_CHECK_FUNCS([setpflags])
AC_CHECK_FUNCS([setppriv])
AC_CHECK_FUNCS([priv_basicset])
AC_CHECK_HEADERS([priv.h])
AC_ARG_WITH([solaris-contracts],
[ --with-solaris-contracts Enable Solaris process contracts (experimental)],
[
AC_CHECK_LIB([contract], [ct_tmpl_activate],
[ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1],
[Define if you have Solaris process contracts])
LIBS="$LIBS -lcontract"
SPC_MSG="yes" ], )
],
)
AC_ARG_WITH([solaris-projects],
[ --with-solaris-projects Enable Solaris projects (experimental)],
[
AC_CHECK_LIB([project], [setproject],
[ AC_DEFINE([USE_SOLARIS_PROJECTS], [1],
[Define if you have Solaris projects])
LIBS="$LIBS -lproject"
SP_MSG="yes" ], )
],
)
AC_ARG_WITH([solaris-privs],
[ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)],
[
AC_MSG_CHECKING([for Solaris/Illumos privilege support])
if test "x$ac_cv_func_setppriv" = "xyes" -a \
"x$ac_cv_header_priv_h" = "xyes" ; then
SOLARIS_PRIVS=yes
AC_MSG_RESULT([found])
AC_DEFINE([NO_UID_RESTORATION_TEST], [1],
[Define to disable UID restoration test])
AC_DEFINE([USE_SOLARIS_PRIVS], [1],
[Define if you have Solaris privileges])
SPP_MSG="yes"
else
AC_MSG_RESULT([not found])
AC_MSG_ERROR([*** must have support for Solaris privileges to use --with-solaris-privs])
fi
],
)
TEST_SHELL=$SHELL # let configure find us a capable shell
;;
*-*-sunos4*)
CPPFLAGS="$CPPFLAGS -DSUNOS4"
AC_CHECK_FUNCS([getpwanam])
AC_DEFINE([PAM_SUN_CODEBASE])
conf_utmp_location=/etc/utmp
conf_wtmp_location=/var/adm/wtmp
conf_lastlog_location=/var/adm/lastlog
AC_DEFINE([USE_PIPES])
AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx])
;;
*-ncr-sysv*)
LIBS="$LIBS -lc89"
AC_DEFINE([USE_PIPES])
AC_DEFINE([SSHD_ACQUIRES_CTTY])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
;;
*-sni-sysv*)
# /usr/ucblib MUST NOT be searched on ReliantUNIX
AC_CHECK_LIB([dl], [dlsym], ,)
# -lresolv needs to be at the end of LIBS or DNS lookups break
AC_CHECK_LIB([resolv], [res_query], [ LIBS="$LIBS -lresolv" ])
IPADDR_IN_DISPLAY=yes
AC_DEFINE([USE_PIPES])
AC_DEFINE([IP_TOS_IS_BROKEN])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([SSHD_ACQUIRES_CTTY])
external_path_file=/etc/default/login
# /usr/ucblib/libucb.a no longer needed on ReliantUNIX
# Attention: always take care to bind libsocket and libnsl before libc,
# otherwise you will find lots of "SIOCGPGRP errno 22" on syslog
;;
# UnixWare 1.x, UnixWare 2.x, and others based on code from Univel.
*-*-sysv4.2*)
AC_DEFINE([USE_PIPES])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd])
AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
TEST_SHELL=$SHELL # let configure find us a capable shell
;;
# UnixWare 7.x, OpenUNIX 8
*-*-sysv5*)
CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf"
AC_DEFINE([UNIXWARE_LONG_PASSWORDS], [1], [Support passwords > 8 chars])
AC_DEFINE([USE_PIPES])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_GETADDRINFO])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([PASSWD_NEEDS_USERNAME])
AC_DEFINE([BROKEN_TCGETATTR_ICANON])
TEST_SHELL=$SHELL # let configure find us a capable shell
check_for_libcrypt_later=1
case "$host" in
*-*-sysv5SCO_SV*) # SCO OpenServer 6.x
maildir=/var/spool/mail
AC_DEFINE([BROKEN_UPDWTMPX])
AC_CHECK_LIB([prot], [getluid], [ LIBS="$LIBS -lprot"
AC_CHECK_FUNCS([getluid setluid], , , [-lprot])
], , )
;;
*) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"])
;;
esac
;;
*-*-sysv*)
;;
# SCO UNIX and OEM versions of SCO UNIX
*-*-sco3.2v4*)
AC_MSG_ERROR("This Platform is no longer supported.")
;;
# SCO OpenServer 5.x
*-*-sco3.2v5*)
if test -z "$GCC"; then
CFLAGS="$CFLAGS -belf"
fi
LIBS="$LIBS -lprot -lx -ltinfo -lm"
no_dev_ptmx=1
AC_DEFINE([USE_PIPES])
AC_DEFINE([HAVE_SECUREWARE])
AC_DEFINE([DISABLE_SHADOW])
AC_DEFINE([DISABLE_FD_PASSING])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_GETADDRINFO])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([WITH_ABBREV_NO_TTY])
AC_DEFINE([BROKEN_UPDWTMPX])
AC_DEFINE([PASSWD_NEEDS_USERNAME])
AC_CHECK_FUNCS([getluid setluid])
MANTYPE=man
TEST_SHELL=$SHELL # let configure find us a capable shell
SKIP_DISABLE_LASTLOG_DEFINE=yes
;;
*-dec-osf*)
AC_MSG_CHECKING([for Digital Unix SIA])
no_osfsia=""
AC_ARG_WITH([osfsia],
[ --with-osfsia Enable Digital Unix SIA],
[
if test "x$withval" = "xno" ; then
AC_MSG_RESULT([disabled])
no_osfsia=1
fi
],
)
if test -z "$no_osfsia" ; then
if test -f /etc/sia/matrix.conf; then
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_OSF_SIA], [1],
[Define if you have Digital Unix Security
Integration Architecture])
AC_DEFINE([DISABLE_LOGIN], [1],
[Define if you don't want to use your
system's login() call])
AC_DEFINE([DISABLE_FD_PASSING])
LIBS="$LIBS -lsecurity -ldb -lm -laud"
SIA_MSG="yes"
else
AC_MSG_RESULT([no])
AC_DEFINE([LOCKED_PASSWD_SUBSTR], ["Nologin"],
[String used in /etc/passwd to denote locked account])
fi
fi
AC_DEFINE([BROKEN_GETADDRINFO])
AC_DEFINE([SETEUID_BREAKS_SETUID])
AC_DEFINE([BROKEN_SETREUID])
AC_DEFINE([BROKEN_SETREGID])
AC_DEFINE([BROKEN_READV_COMPARISON], [1], [Can't do comparisons on readv])
;;
*-*-nto-qnx*)
AC_DEFINE([USE_PIPES])
AC_DEFINE([NO_X11_UNIX_SOCKETS])
AC_DEFINE([DISABLE_LASTLOG])
AC_DEFINE([SSHD_ACQUIRES_CTTY])
AC_DEFINE([BROKEN_SHADOW_EXPIRE], [1], [QNX shadow support is broken])
enable_etc_default_login=no # has incompatible /etc/default/login
case "$host" in
*-*-nto-qnx6*)
AC_DEFINE([DISABLE_FD_PASSING])
;;
esac
;;
*-*-ultrix*)
AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1])
AC_DEFINE([NEED_SETPGRP])
AC_DEFINE([HAVE_SYS_SYSLOG_H], [1], [Force use of sys/syslog.h on Ultrix])
;;
*-*-lynxos)
CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"
AC_DEFINE([BROKEN_SETVBUF], [1],
[LynxOS has broken setvbuf() implementation])
;;
esac
AC_MSG_CHECKING([compiler and flags for sanity])
AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]], [[ exit(0); ]])],
[ AC_MSG_RESULT([yes]) ],
[
AC_MSG_RESULT([no])
AC_MSG_ERROR([*** compiler cannot create working executables, check config.log ***])
],
[ AC_MSG_WARN([cross compiling: not checking compiler sanity]) ]
)
dnl Checks for header files.
# Checks for libraries.
AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])])
dnl IRIX and Solaris 2.5.1 have dirname() in libgen
AC_CHECK_FUNCS([dirname], [AC_CHECK_HEADERS([libgen.h])] , [
AC_CHECK_LIB([gen], [dirname], [
AC_CACHE_CHECK([for broken dirname],
ac_cv_have_broken_dirname, [
save_LIBS="$LIBS"
LIBS="$LIBS -lgen"
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <libgen.h>
#include <string.h>
int main(int argc, char **argv) {
char *s, buf[32];
strncpy(buf,"/etc", 32);
s = dirname(buf);
if (!s || strncmp(s, "/", 32) != 0) {
exit(1);
} else {
exit(0);
}
}
]])],
[ ac_cv_have_broken_dirname="no" ],
[ ac_cv_have_broken_dirname="yes" ],
[ ac_cv_have_broken_dirname="no" ],
)
LIBS="$save_LIBS"
])
if test "x$ac_cv_have_broken_dirname" = "xno" ; then
LIBS="$LIBS -lgen"
AC_DEFINE([HAVE_DIRNAME])
AC_CHECK_HEADERS([libgen.h])
fi
])
])
AC_CHECK_FUNC([getspnam], ,
[AC_CHECK_LIB([gen], [getspnam], [LIBS="$LIBS -lgen"])])
AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1],
[Define if you have the basename function.])])
dnl zlib is required
AC_ARG_WITH([zlib],
[ --with-zlib=PATH Use zlib in PATH],
[ if test "x$withval" = "xno" ; then
AC_MSG_ERROR([*** zlib is required ***])
elif test "x$withval" != "xyes"; then
if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}"
else
LDFLAGS="-L${withval} ${LDFLAGS}"
fi
fi
if test -d "$withval/include"; then
CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
else
CPPFLAGS="-I${withval} ${CPPFLAGS}"
fi
fi ]
)
AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])])
AC_CHECK_LIB([z], [deflate], ,
[
saved_CPPFLAGS="$CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
save_LIBS="$LIBS"
dnl Check default zlib install dir
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/lib -R/usr/local/lib ${saved_LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}"
else
LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}"
fi
CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}"
LIBS="$LIBS -lz"
AC_TRY_LINK_FUNC([deflate], [AC_DEFINE([HAVE_LIBZ])],
[
AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***])
]
)
]
)
AC_ARG_WITH([zlib-version-check],
[ --without-zlib-version-check Disable zlib version check],
[ if test "x$withval" = "xno" ; then
zlib_check_nonfatal=1
fi
]
)
AC_MSG_CHECKING([for possibly buggy zlib])
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
]],
[[
int a=0, b=0, c=0, d=0, n, v;
n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d);
if (n != 3 && n != 4)
exit(1);
v = a*1000000 + b*10000 + c*100 + d;
fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v);
/* 1.1.4 is OK */
if (a == 1 && b == 1 && c >= 4)
exit(0);
/* 1.2.3 and up are OK */
if (v >= 1020300)
exit(0);
exit(2);
]])],
AC_MSG_RESULT([no]),
[ AC_MSG_RESULT([yes])
if test -z "$zlib_check_nonfatal" ; then
AC_MSG_ERROR([*** zlib too old - check config.log ***
Your reported zlib version has known security problems. It's possible your
vendor has fixed these problems without changing the version number. If you
are sure this is the case, you can disable the check by running
"./configure --without-zlib-version-check".
If you are in doubt, upgrade zlib to version 1.2.3 or greater.
See http://www.gzip.org/zlib/ for details.])
else
AC_MSG_WARN([zlib version may have security problems])
fi
],
[ AC_MSG_WARN([cross compiling: not checking zlib version]) ]
)
dnl UnixWare 2.x
AC_CHECK_FUNC([strcasecmp],
[], [ AC_CHECK_LIB([resolv], [strcasecmp], [LIBS="$LIBS -lresolv"]) ]
)
AC_CHECK_FUNCS([utimes],
[], [ AC_CHECK_LIB([c89], [utimes], [AC_DEFINE([HAVE_UTIMES])
LIBS="$LIBS -lc89"]) ]
)
dnl Checks for libutil functions
AC_CHECK_HEADERS([bsd/libutil.h libutil.h])
AC_SEARCH_LIBS([fmt_scaled], [util bsd])
AC_SEARCH_LIBS([scan_scaled], [util bsd])
AC_SEARCH_LIBS([login], [util bsd])
AC_SEARCH_LIBS([logout], [util bsd])
AC_SEARCH_LIBS([logwtmp], [util bsd])
AC_SEARCH_LIBS([openpty], [util bsd])
AC_SEARCH_LIBS([updwtmp], [util bsd])
AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp])
# On some platforms, inet_ntop and gethostbyname may be found in libresolv
# or libnsl.
AC_SEARCH_LIBS([inet_ntop], [resolv nsl])
AC_SEARCH_LIBS([gethostbyname], [resolv nsl])
# "Particular Function Checks"
# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
AC_FUNC_STRFTIME
AC_FUNC_MALLOC
AC_FUNC_REALLOC
# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL;
AC_MSG_CHECKING([if calloc(0, N) returns non-null])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[ #include <stdlib.h> ]],
[[ void *p = calloc(0, 1); exit(p == NULL); ]]
)],
[ func_calloc_0_nonnull=yes ],
[ func_calloc_0_nonnull=no ],
[ AC_MSG_WARN([cross compiling: assuming same as malloc])
func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull"]
)
AC_MSG_RESULT([$func_calloc_0_nonnull])
if test "x$func_calloc_0_nonnull" = "xyes"; then
AC_DEFINE(HAVE_CALLOC, 1, [calloc(0, x) returns non-null])
else
AC_DEFINE(HAVE_CALLOC, 0, [calloc(0, x) returns NULL])
AC_DEFINE(calloc, rpl_calloc,
[Define to rpl_calloc if the replacement function should be used.])
fi
# Check for ALTDIRFUNC glob() extension
AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support])
AC_EGREP_CPP([FOUNDIT],
[
#include <glob.h>
#ifdef GLOB_ALTDIRFUNC
FOUNDIT
#endif
],
[
AC_DEFINE([GLOB_HAS_ALTDIRFUNC], [1],
[Define if your system glob() function has
the GLOB_ALTDIRFUNC extension])
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
]
)
# Check for g.gl_matchc glob() extension
AC_MSG_CHECKING([for gl_matchc field in glob_t])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <glob.h> ]],
[[ glob_t g; g.gl_matchc = 1; ]])],
[
AC_DEFINE([GLOB_HAS_GL_MATCHC], [1],
[Define if your system glob() function has
gl_matchc options in glob_t])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
])
# Check for g.gl_statv glob() extension
AC_MSG_CHECKING([for gl_statv and GLOB_KEEPSTAT extensions for glob])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <glob.h> ]], [[
#ifndef GLOB_KEEPSTAT
#error "glob does not support GLOB_KEEPSTAT extension"
#endif
glob_t g;
g.gl_statv = NULL;
]])],
[
AC_DEFINE([GLOB_HAS_GL_STATV], [1],
[Define if your system glob() function has
gl_statv options in glob_t])
AC_MSG_RESULT([yes])
], [
AC_MSG_RESULT([no])
])
AC_CHECK_DECLS([GLOB_NOMATCH], , , [#include <glob.h>])
AC_CHECK_DECL([VIS_ALL], ,
AC_DEFINE(BROKEN_STRNVIS, 1, [missing VIS_ALL]), [#include <vis.h>])
AC_MSG_CHECKING([whether struct dirent allocates space for d_name])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <dirent.h>]],
[[
struct dirent d;
exit(sizeof(d.d_name)<=sizeof(char));
]])],
[AC_MSG_RESULT([yes])],
[
AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1],
[Define if your struct dirent expects you to
allocate extra space for d_name])
],
[
AC_MSG_WARN([cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME])
AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME])
]
)
AC_MSG_CHECKING([for /proc/pid/fd directory])
if test -d "/proc/$$/fd" ; then
AC_DEFINE([HAVE_PROC_PID], [1], [Define if you have /proc/$pid/fd])
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
# Check whether user wants to use ldns
LDNS_MSG="no"
AC_ARG_WITH(ldns,
[ --with-ldns[[=PATH]] Use ldns for DNSSEC support (optionally in PATH)],
[
ldns=""
if test "x$withval" = "xyes" ; then
AC_PATH_TOOL([LDNSCONFIG], [ldns-config], [no])
if test "x$LDNSCONFIG" = "xno"; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBS="-lldns $LIBS"
ldns=yes
else
LIBS="$LIBS `$LDNSCONFIG --libs`"
CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`"
ldns=yes
fi
elif test "x$withval" != "xno" ; then
CPPFLAGS="$CPPFLAGS -I${withval}/include"
LDFLAGS="$LDFLAGS -L${withval}/lib"
LIBS="-lldns $LIBS"
ldns=yes
fi
# Verify that it works.
if test "x$ldns" = "xyes" ; then
AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support])
LDNS_MSG="yes"
AC_MSG_CHECKING([for ldns support])
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ldns/ldns.h>
int main() { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); }
]])
],
[AC_MSG_RESULT(yes)],
[
AC_MSG_RESULT(no)
AC_MSG_ERROR([** Incomplete or missing ldns libraries.])
])
fi
])
# Check whether user wants libedit support
LIBEDIT_MSG="no"
AC_ARG_WITH([libedit],
[ --with-libedit[[=PATH]] Enable libedit support for sftp],
[ if test "x$withval" != "xno" ; then
if test "x$withval" = "xyes" ; then
AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
if test "x$PKGCONFIG" != "xno"; then
AC_MSG_CHECKING([if $PKGCONFIG knows about libedit])
if "$PKGCONFIG" libedit; then
AC_MSG_RESULT([yes])
use_pkgconfig_for_libedit=yes
else
AC_MSG_RESULT([no])
fi
fi
else
CPPFLAGS="$CPPFLAGS -I${withval}/include"
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
fi
if test "x$use_pkgconfig_for_libedit" = "xyes"; then
LIBEDIT=`$PKGCONFIG --libs libedit`
CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`"
else
LIBEDIT="-ledit -lcurses"
fi
OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'`
AC_CHECK_LIB([edit], [el_init],
[ AC_DEFINE([USE_LIBEDIT], [1], [Use libedit for sftp])
LIBEDIT_MSG="yes"
AC_SUBST([LIBEDIT])
],
[ AC_MSG_ERROR([libedit not found]) ],
[ $OTHERLIBS ]
)
AC_MSG_CHECKING([if libedit version is compatible])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[ #include <histedit.h> ]],
[[
int i = H_SETSIZE;
el_init("", NULL, NULL, NULL);
exit(0);
]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([libedit version is not compatible]) ]
)
fi ]
)
AUDIT_MODULE=none
AC_ARG_WITH([audit],
[ --with-audit=module Enable audit support (modules=debug,bsm,linux)],
[
AC_MSG_CHECKING([for supported audit module])
case "$withval" in
bsm)
AC_MSG_RESULT([bsm])
AUDIT_MODULE=bsm
dnl Checks for headers, libs and functions
AC_CHECK_HEADERS([bsm/audit.h], [],
[AC_MSG_ERROR([BSM enabled and bsm/audit.h not found])],
[
#ifdef HAVE_TIME_H
# include <time.h>
#endif
]
)
AC_CHECK_LIB([bsm], [getaudit], [],
[AC_MSG_ERROR([BSM enabled and required library not found])])
AC_CHECK_FUNCS([getaudit], [],
[AC_MSG_ERROR([BSM enabled and required function not found])])
# These are optional
AC_CHECK_FUNCS([getaudit_addr aug_get_machine])
AC_DEFINE([USE_BSM_AUDIT], [1], [Use BSM audit module])
if test "$sol2ver" -ge 11; then
SSHDLIBS="$SSHDLIBS -lscf"
AC_DEFINE([BROKEN_BSM_API], [1],
[The system has incomplete BSM API])
fi
;;
linux)
AC_MSG_RESULT([linux])
AUDIT_MODULE=linux
dnl Checks for headers, libs and functions
AC_CHECK_HEADERS([libaudit.h])
SSHDLIBS="$SSHDLIBS -laudit"
AC_DEFINE([USE_LINUX_AUDIT], [1], [Use Linux audit module])
;;
debug)
AUDIT_MODULE=debug
AC_MSG_RESULT([debug])
AC_DEFINE([SSH_AUDIT_EVENTS], [1], [Use audit debugging module])
;;
no)
AC_MSG_RESULT([no])
;;
*)
AC_MSG_ERROR([Unknown audit module $withval])
;;
esac ]
)
AC_ARG_WITH([pie],
[ --with-pie Build Position Independent Executables if possible], [
if test "x$withval" = "xno"; then
use_pie=no
fi
if test "x$withval" = "xyes"; then
use_pie=yes
fi
]
)
if test "x$use_pie" = "x"; then
use_pie=no
fi
if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then
# Turn off automatic PIE when toolchain hardening is off.
use_pie=no
fi
if test "x$use_pie" = "xauto"; then
# Automatic PIE requires gcc >= 4.x
AC_MSG_CHECKING([for gcc >= 4.x])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#if !defined(__GNUC__) || __GNUC__ < 4
#error gcc is too old
#endif
]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
use_pie=no ]
)
fi
if test "x$use_pie" != "xno"; then
SAVED_CFLAGS="$CFLAGS"
SAVED_LDFLAGS="$LDFLAGS"
OSSH_CHECK_CFLAG_COMPILE([-fPIE])
OSSH_CHECK_LDFLAG_LINK([-pie])
# We use both -fPIE and -pie or neither.
AC_MSG_CHECKING([whether both -fPIE and -pie are supported])
if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \
echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
CFLAGS="$SAVED_CFLAGS"
LDFLAGS="$SAVED_LDFLAGS"
fi
fi
dnl Checks for library functions. Please keep in alphabetical order
AC_CHECK_FUNCS([ \
Blowfish_initstate \
Blowfish_expandstate \
Blowfish_expand0state \
Blowfish_stream2word \
asprintf \
b64_ntop \
__b64_ntop \
b64_pton \
__b64_pton \
bcopy \
bcrypt_pbkdf \
bindresvport_sa \
blf_enc \
bzero \
cap_rights_limit \
clock \
closefrom \
dirfd \
endgrent \
err \
errx \
explicit_bzero \
fchmod \
+ fchmodat \
fchown \
+ fchownat \
flock \
freeaddrinfo \
freezero \
fstatfs \
fstatvfs \
futimes \
getaddrinfo \
getcwd \
getgrouplist \
getline \
getnameinfo \
getopt \
getpagesize \
getpeereid \
getpeerucred \
getpgid \
_getpty \
getrlimit \
getrandom \
getsid \
getttyent \
glob \
group_from_gid \
inet_aton \
inet_ntoa \
inet_ntop \
innetgr \
llabs \
login_getcapbool \
md5_crypt \
memmove \
memset_s \
mkdtemp \
ngetaddrinfo \
nsleep \
ogetaddrinfo \
openlog_r \
pledge \
poll \
prctl \
pstat \
raise \
readpassphrase \
reallocarray \
recvmsg \
recallocarray \
rresvport_af \
sendmsg \
setdtablesize \
setegid \
setenv \
seteuid \
setgroupent \
setgroups \
setlinebuf \
setlogin \
setpassent\
setpcred \
setproctitle \
setregid \
setreuid \
setrlimit \
setsid \
setvbuf \
sigaction \
sigvec \
snprintf \
socketpair \
statfs \
statvfs \
strcasestr \
strdup \
strerror \
strlcat \
strlcpy \
strmode \
strndup \
strnlen \
strnvis \
strptime \
strsignal \
strtonum \
strtoll \
strtoul \
strtoull \
swap32 \
sysconf \
tcgetpgrp \
timingsafe_bcmp \
truncate \
unsetenv \
updwtmpx \
+ utimensat \
user_from_uid \
usleep \
vasprintf \
vsnprintf \
waitpid \
warn \
])
AC_CHECK_DECLS([bzero])
dnl Wide character support.
AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth])
TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes}
AC_MSG_CHECKING([for utf8 locale support])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <locale.h>
#include <stdlib.h>
]], [[
char *loc = setlocale(LC_CTYPE, "en_US.UTF-8");
if (loc != NULL)
exit(0);
exit(1);
]])],
AC_MSG_RESULT(yes),
[AC_MSG_RESULT(no)
TEST_SSH_UTF8=no],
AC_MSG_WARN([cross compiling: assuming yes])
)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[[ #include <ctype.h> ]],
[[ return (isblank('a')); ]])],
[AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).])
])
disable_pkcs11=
AC_ARG_ENABLE([pkcs11],
[ --disable-pkcs11 disable PKCS#11 support code [no]],
[
if test "x$enableval" = "xno" ; then
disable_pkcs11=1
fi
]
)
# PKCS11 depends on OpenSSL.
if test "x$openssl" = "xyes" && test "x$disable_pkcs11" = "x"; then
# PKCS#11 support requires dlopen() and co
AC_SEARCH_LIBS([dlopen], [dl],
AC_CHECK_DECL([RTLD_NOW],
AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support]),
[], [#include <dlfcn.h>]
)
)
fi
# IRIX has a const char return value for gai_strerror()
AC_CHECK_FUNCS([gai_strerror], [
AC_DEFINE([HAVE_GAI_STRERROR])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
const char *gai_strerror(int);
]], [[
char *str;
str = gai_strerror(0);
]])], [
AC_DEFINE([HAVE_CONST_GAI_STRERROR_PROTO], [1],
[Define if gai_strerror() returns const char *])], [])])
AC_SEARCH_LIBS([nanosleep], [rt posix4], [AC_DEFINE([HAVE_NANOSLEEP], [1],
[Some systems put nanosleep outside of libc])])
AC_SEARCH_LIBS([clock_gettime], [rt],
[AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Have clock_gettime])])
dnl Make sure prototypes are defined for these before using them.
AC_CHECK_DECL([strsep],
[AC_CHECK_FUNCS([strsep])],
[],
[
#ifdef HAVE_STRING_H
# include <string.h>
#endif
])
dnl tcsendbreak might be a macro
AC_CHECK_DECL([tcsendbreak],
[AC_DEFINE([HAVE_TCSENDBREAK])],
[AC_CHECK_FUNCS([tcsendbreak])],
[#include <termios.h>]
)
AC_CHECK_DECLS([h_errno], , ,[#include <netdb.h>])
AC_CHECK_DECLS([SHUT_RD], , ,
[
#include <sys/types.h>
#include <sys/socket.h>
])
AC_CHECK_DECLS([O_NONBLOCK], , ,
[
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
])
AC_CHECK_DECLS([readv, writev], , , [
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
])
AC_CHECK_DECLS([MAXSYMLINKS], , , [
#include <sys/param.h>
])
AC_CHECK_DECLS([offsetof], , , [
#include <stddef.h>
])
# extra bits for select(2)
AC_CHECK_DECLS([howmany, NFDBITS], [], [], [[
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SYSMACROS_H
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
]])
AC_CHECK_TYPES([fd_mask], [], [], [[
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
]])
AC_CHECK_FUNCS([setresuid], [
dnl Some platorms have setresuid that isn't implemented, test for this
AC_MSG_CHECKING([if setresuid seems to work])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <errno.h>
]], [[
errno=0;
setresuid(0,0,0);
if (errno==ENOSYS)
exit(1);
else
exit(0);
]])],
[AC_MSG_RESULT([yes])],
[AC_DEFINE([BROKEN_SETRESUID], [1],
[Define if your setresuid() is broken])
AC_MSG_RESULT([not implemented])],
[AC_MSG_WARN([cross compiling: not checking setresuid])]
)
])
AC_CHECK_FUNCS([setresgid], [
dnl Some platorms have setresgid that isn't implemented, test for this
AC_MSG_CHECKING([if setresgid seems to work])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <errno.h>
]], [[
errno=0;
setresgid(0,0,0);
if (errno==ENOSYS)
exit(1);
else
exit(0);
]])],
[AC_MSG_RESULT([yes])],
[AC_DEFINE([BROKEN_SETRESGID], [1],
[Define if your setresgid() is broken])
AC_MSG_RESULT([not implemented])],
[AC_MSG_WARN([cross compiling: not checking setresuid])]
)
])
AC_CHECK_FUNCS([realpath], [
dnl the sftp v3 spec says SSH_FXP_REALPATH will "canonicalize any given
dnl path name", however some implementations of realpath (and some
dnl versions of the POSIX spec) do not work on non-existent files,
dnl so we use the OpenBSD implementation on those platforms.
AC_MSG_CHECKING([if realpath works with non-existent files])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
]], [[
char buf[PATH_MAX];
if (realpath("/opensshnonexistentfilename1234", buf) == NULL)
if (errno == ENOENT)
exit(1);
exit(0);
]])],
[AC_MSG_RESULT([yes])],
[AC_DEFINE([BROKEN_REALPATH], [1],
[realpath does not work with nonexistent files])
AC_MSG_RESULT([no])],
[AC_MSG_WARN([cross compiling: assuming working])]
)
])
AC_MSG_CHECKING([for working fflush(NULL)])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[#include <stdio.h>]], [[fflush(NULL); exit(0);]])],
AC_MSG_RESULT([yes]),
[AC_MSG_RESULT([no])
AC_DEFINE([FFLUSH_NULL_BUG], [1],
[define if fflush(NULL) does not work])],
AC_MSG_WARN([cross compiling: assuming working])
)
dnl Checks for time functions
AC_CHECK_FUNCS([gettimeofday time])
dnl Checks for utmp functions
AC_CHECK_FUNCS([endutent getutent getutid getutline pututline setutent])
AC_CHECK_FUNCS([utmpname])
dnl Checks for utmpx functions
AC_CHECK_FUNCS([endutxent getutxent getutxid getutxline getutxuser pututxline])
AC_CHECK_FUNCS([setutxdb setutxent utmpxname])
dnl Checks for lastlog functions
AC_CHECK_FUNCS([getlastlogxbyname])
AC_CHECK_FUNC([daemon],
[AC_DEFINE([HAVE_DAEMON], [1], [Define if your libraries define daemon()])],
[AC_CHECK_LIB([bsd], [daemon],
[LIBS="$LIBS -lbsd"; AC_DEFINE([HAVE_DAEMON])])]
)
AC_CHECK_FUNC([getpagesize],
[AC_DEFINE([HAVE_GETPAGESIZE], [1],
[Define if your libraries define getpagesize()])],
[AC_CHECK_LIB([ucb], [getpagesize],
[LIBS="$LIBS -lucb"; AC_DEFINE([HAVE_GETPAGESIZE])])]
)
# Check for broken snprintf
if test "x$ac_cv_func_snprintf" = "xyes" ; then
AC_MSG_CHECKING([whether snprintf correctly terminates long strings])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[
char b[5];
snprintf(b,5,"123456789");
exit(b[4]!='\0');
]])],
[AC_MSG_RESULT([yes])],
[
AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_SNPRINTF], [1],
[Define if your snprintf is busted])
AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor])
],
[ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ]
)
fi
if test "x$ac_cv_func_snprintf" = "xyes" ; then
AC_MSG_CHECKING([whether snprintf understands %zu])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <stdio.h>
]],
[[
size_t a = 1, b = 2;
char z[128];
snprintf(z, sizeof z, "%zu%zu", a, b);
exit(strcmp(z, "12"));
]])],
[AC_MSG_RESULT([yes])],
[
AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_SNPRINTF], [1],
[snprintf does not understand %zu])
],
[ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ]
)
fi
# We depend on vsnprintf returning the right thing on overflow: the
# number of characters it tried to create (as per SUSv3)
if test "x$ac_cv_func_vsnprintf" = "xyes" ; then
AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <stdio.h>
#include <stdarg.h>
int x_snprintf(char *str, size_t count, const char *fmt, ...)
{
size_t ret;
va_list ap;
va_start(ap, fmt);
ret = vsnprintf(str, count, fmt, ap);
va_end(ap);
return ret;
}
]], [[
char x[1];
if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11)
return 1;
if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11)
return 1;
return 0;
]])],
[AC_MSG_RESULT([yes])],
[
AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_SNPRINTF], [1],
[Define if your snprintf is busted])
AC_MSG_WARN([****** Your vsnprintf() function is broken, complain to your vendor])
],
[ AC_MSG_WARN([cross compiling: Assuming working vsnprintf()]) ]
)
fi
# On systems where [v]snprintf is broken, but is declared in stdio,
# check that the fmt argument is const char * or just char *.
# This is only useful for when BROKEN_SNPRINTF
AC_MSG_CHECKING([whether snprintf can declare const char *fmt])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
int snprintf(char *a, size_t b, const char *c, ...) { return 0; }
]], [[
snprintf(0, 0, 0);
]])],
[AC_MSG_RESULT([yes])
AC_DEFINE([SNPRINTF_CONST], [const],
[Define as const if snprintf() can declare const char *fmt])],
[AC_MSG_RESULT([no])
AC_DEFINE([SNPRINTF_CONST], [/* not const */])])
# Check for missing getpeereid (or equiv) support
NO_PEERCHECK=""
if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then
AC_MSG_CHECKING([whether system supports SO_PEERCRED getsockopt])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>]], [[int i = SO_PEERCRED;]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_SO_PEERCRED], [1], [Have PEERCRED socket option])
], [AC_MSG_RESULT([no])
NO_PEERCHECK=1
])
fi
dnl see whether mkstemp() requires XXXXXX
if test "x$ac_cv_func_mkdtemp" = "xyes" ; then
AC_MSG_CHECKING([for (overly) strict mkstemp])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdlib.h>
]], [[
char template[]="conftest.mkstemp-test";
if (mkstemp(template) == -1)
exit(1);
unlink(template);
exit(0);
]])],
[
AC_MSG_RESULT([no])
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_STRICT_MKSTEMP], [1], [Silly mkstemp()])
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_STRICT_MKSTEMP])
]
)
fi
dnl make sure that openpty does not reacquire controlling terminal
if test ! -z "$check_for_openpty_ctty_bug"; then
AC_MSG_CHECKING([if openpty correctly handles controlling tty])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
]], [[
pid_t pid;
int fd, ptyfd, ttyfd, status;
pid = fork();
if (pid < 0) { /* failed */
exit(1);
} else if (pid > 0) { /* parent */
waitpid(pid, &status, 0);
if (WIFEXITED(status))
exit(WEXITSTATUS(status));
else
exit(2);
} else { /* child */
close(0); close(1); close(2);
setsid();
openpty(&ptyfd, &ttyfd, NULL, NULL, NULL);
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
if (fd >= 0)
exit(3); /* Acquired ctty: broken */
else
exit(0); /* Did not acquire ctty: OK */
}
]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
AC_DEFINE([SSHD_ACQUIRES_CTTY])
],
[
AC_MSG_RESULT([cross-compiling, assuming yes])
]
)
fi
if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then
AC_MSG_CHECKING([if getaddrinfo seems to work])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/in.h>
#define TEST_PORT "2222"
]], [[
int err, sock;
struct addrinfo *gai_ai, *ai, hints;
char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
if (err != 0) {
fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
exit(1);
}
for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family != AF_INET6)
continue;
err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV);
if (err != 0) {
if (err == EAI_SYSTEM)
perror("getnameinfo EAI_SYSTEM");
else
fprintf(stderr, "getnameinfo failed: %s\n",
gai_strerror(err));
exit(2);
}
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0)
perror("socket");
if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
if (errno == EBADF)
exit(3);
}
}
exit(0);
]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_GETADDRINFO])
],
[
AC_MSG_RESULT([cross-compiling, assuming yes])
]
)
fi
if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
test "x$check_for_aix_broken_getaddrinfo" = "x1"; then
AC_MSG_CHECKING([if getaddrinfo seems to work])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <netinet/in.h>
#define TEST_PORT "2222"
]], [[
int err, sock;
struct addrinfo *gai_ai, *ai, hints;
char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai);
if (err != 0) {
fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err));
exit(1);
}
for (ai = gai_ai; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
continue;
err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop,
sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV);
if (ai->ai_family == AF_INET && err != 0) {
perror("getnameinfo");
exit(2);
}
}
exit(0);
]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE([AIX_GETNAMEINFO_HACK], [1],
[Define if you have a getaddrinfo that fails
for the all-zeros IPv6 address])
],
[
AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_GETADDRINFO])
],
[
AC_MSG_RESULT([cross-compiling, assuming no])
]
)
fi
if test "x$ac_cv_func_getaddrinfo" = "xyes"; then
AC_CHECK_DECLS(AI_NUMERICSERV, , ,
[#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>])
fi
if test "x$check_for_conflicting_getspnam" = "x1"; then
AC_MSG_CHECKING([for conflicting getspnam in shadow.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <shadow.h> ]],
[[ exit(0); ]])],
[
AC_MSG_RESULT([no])
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([GETSPNAM_CONFLICTING_DEFS], [1],
[Conflicting defs for getspnam])
]
)
fi
dnl NetBSD added an strnvis and unfortunately made it incompatible with the
dnl existing one in OpenBSD and Linux's libbsd (the former having existed
dnl for over ten years). Despite this incompatibility being reported during
dnl development (see http://gnats.netbsd.org/44977) they still shipped it.
dnl Even more unfortunately FreeBSD and later MacOS picked up this incompatible
dnl implementation. Try to detect this mess, and assume the only safe option
dnl if we're cross compiling.
dnl
dnl OpenBSD, 2001: strnvis(char *dst, const char *src, size_t dlen, int flag);
dnl NetBSD: 2012, strnvis(char *dst, size_t dlen, const char *src, int flag);
if test "x$ac_cv_func_strnvis" = "xyes"; then
AC_MSG_CHECKING([for working strnvis])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <vis.h>
static void sighandler(int sig) { _exit(1); }
]], [[
char dst[16];
signal(SIGSEGV, sighandler);
if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0)
exit(0);
exit(1)
]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis detected broken])],
[AC_MSG_WARN([cross compiling: assuming broken])
AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis assumed broken])]
)
fi
AC_CHECK_FUNCS([getpgrp],[
AC_MSG_CHECKING([if getpgrp accepts zero args])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[$ac_includes_default]], [[ getpgrp(); ]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([GETPGRP_VOID], [1], [getpgrp takes zero args])],
[ AC_MSG_RESULT([no])
AC_DEFINE([GETPGRP_VOID], [0], [getpgrp takes one arg])]
)
])
# Search for OpenSSL
saved_CPPFLAGS="$CPPFLAGS"
saved_LDFLAGS="$LDFLAGS"
AC_ARG_WITH([ssl-dir],
[ --with-ssl-dir=PATH Specify path to OpenSSL installation ],
[
if test "x$openssl" = "xno" ; then
AC_MSG_ERROR([cannot use --with-ssl-dir when OpenSSL disabled])
fi
if test "x$withval" != "xno" ; then
case "$withval" in
# Relative paths
./*|../*) withval="`pwd`/$withval"
esac
if test -d "$withval/lib"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib ${LDFLAGS}"
fi
elif test -d "$withval/lib64"; then
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval}/lib64 -R${withval}/lib64 ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval}/lib64 ${rpath_opt}${withval}/lib64 ${LDFLAGS}"
else
LDFLAGS="-L${withval}/lib64 ${LDFLAGS}"
fi
else
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ if test -n "${rpath_opt}"; then
+ LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}"
else
LDFLAGS="-L${withval} ${LDFLAGS}"
fi
fi
if test -d "$withval/include"; then
CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
else
CPPFLAGS="-I${withval} ${CPPFLAGS}"
fi
fi
]
)
AC_ARG_WITH([openssl-header-check],
[ --without-openssl-header-check Disable OpenSSL version consistency check],
[
if test "x$withval" = "xno" ; then
openssl_check_nonfatal=1
fi
]
)
openssl_engine=no
AC_ARG_WITH([ssl-engine],
[ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ],
[
if test "x$withval" != "xno" ; then
if test "x$openssl" = "xno" ; then
AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled])
fi
openssl_engine=yes
fi
]
)
if test "x$openssl" = "xyes" ; then
LIBS="-lcrypto $LIBS"
- AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL], [1],
- [Define if your ssl headers are included
- with #include <openssl/header.h>])],
- [
- dnl Check default openssl install dir
- if test -n "${need_dash_r}"; then
- LDFLAGS="-L/usr/local/ssl/lib -R/usr/local/ssl/lib ${saved_LDFLAGS}"
- else
- LDFLAGS="-L/usr/local/ssl/lib ${saved_LDFLAGS}"
- fi
- CPPFLAGS="-I/usr/local/ssl/include ${saved_CPPFLAGS}"
- AC_CHECK_HEADER([openssl/opensslv.h], ,
- [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])])
- AC_TRY_LINK_FUNC([RAND_add], [AC_DEFINE([HAVE_OPENSSL])],
- [
- AC_MSG_ERROR([*** Can't find recent OpenSSL libcrypto (see config.log for details) ***])
- ]
- )
- ]
- )
+ AC_TRY_LINK_FUNC([RAND_add], ,
+ [AC_MSG_ERROR([*** working libcrypto not found, check config.log])])
+ AC_CHECK_HEADER([openssl/opensslv.h], ,
+ [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])])
# Determine OpenSSL header version
AC_MSG_CHECKING([OpenSSL header version])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/opensslv.h>
#define DATA "conftest.sslincver"
]], [[
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
if ((rc = fprintf(fd, "%08lx (%s)\n",
(unsigned long)OPENSSL_VERSION_NUMBER,
OPENSSL_VERSION_TEXT)) < 0)
exit(1);
exit(0);
]])],
[
ssl_header_ver=`cat conftest.sslincver`
AC_MSG_RESULT([$ssl_header_ver])
],
[
AC_MSG_RESULT([not found])
AC_MSG_ERROR([OpenSSL version header not found.])
],
[
AC_MSG_WARN([cross compiling: not checking])
]
)
+ # Determining OpenSSL library version is version dependent.
+ AC_CHECK_FUNCS([OpenSSL_version OpenSSL_version_num])
+
# Determine OpenSSL library version
AC_MSG_CHECKING([OpenSSL library version])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
#include <string.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#define DATA "conftest.ssllibver"
]], [[
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
-
- if ((rc = fprintf(fd, "%08lx (%s)\n", (unsigned long)SSLeay(),
- SSLeay_version(SSLEAY_VERSION))) < 0)
+#ifndef OPENSSL_VERSION
+# define OPENSSL_VERSION SSLEAY_VERSION
+#endif
+#ifndef HAVE_OPENSSL_VERSION
+# define OpenSSL_version SSLeay_version
+#endif
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
+#endif
+ if ((rc = fprintf(fd, "%08lx (%s)\n",
+ (unsigned long)OpenSSL_version_num(),
+ OpenSSL_version(OPENSSL_VERSION))) < 0)
exit(1);
exit(0);
]])],
[
ssl_library_ver=`cat conftest.ssllibver`
# Check version is supported.
case "$ssl_library_ver" in
10000*|0*)
AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")])
;;
100*) ;; # 1.0.x
- 101000[0123456]*)
+ 101000[[0123456]]*)
# https://github.com/openssl/openssl/pull/4613
AC_MSG_ERROR([OpenSSL 1.1.x versions prior to 1.1.0g have a bug that breaks their use with OpenSSH (have "$ssl_library_ver")])
;;
101*) ;; # 1.1.x
200*) ;; # LibreSSL
+ 300*) ;; # OpenSSL development branch.
*)
- AC_MSG_ERROR([OpenSSL > 1.1.x is not yet supported (have "$ssl_library_ver")])
+ AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_library_ver")])
;;
esac
AC_MSG_RESULT([$ssl_library_ver])
],
[
AC_MSG_RESULT([not found])
AC_MSG_ERROR([OpenSSL library not found.])
],
[
AC_MSG_WARN([cross compiling: not checking])
]
)
# Sanity check OpenSSL headers
AC_MSG_CHECKING([whether OpenSSL's headers match the library])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
]], [[
- exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1);
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
+#endif
+ exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1);
]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
if test "x$openssl_check_nonfatal" = "x"; then
AC_MSG_ERROR([Your OpenSSL headers do not match your
library. Check config.log for details.
If you are sure your installation is consistent, you can disable the check
by running "./configure --without-openssl-header-check".
Also see contrib/findssl.sh for help identifying header/library mismatches.
])
else
AC_MSG_WARN([Your OpenSSL headers do not match your
library. Check config.log for details.
Also see contrib/findssl.sh for help identifying header/library mismatches.])
fi
],
[
AC_MSG_WARN([cross compiling: not checking])
]
)
AC_MSG_CHECKING([if programs using OpenSSL functions will link])
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]],
- [[ SSLeay_add_all_algorithms(); ]])],
+ [AC_LANG_PROGRAM([[ #include <openssl/err.h> ]],
+ [[ ERR_load_crypto_strings(); ]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
saved_LIBS="$LIBS"
LIBS="$LIBS -ldl"
AC_MSG_CHECKING([if programs using OpenSSL need -ldl])
AC_LINK_IFELSE(
- [AC_LANG_PROGRAM([[ #include <openssl/evp.h> ]],
- [[ SSLeay_add_all_algorithms(); ]])],
+ [AC_LANG_PROGRAM([[ #include <openssl/err.h> ]],
+ [[ ERR_load_crypto_strings(); ]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
LIBS="$saved_LIBS"
]
)
]
)
AC_CHECK_FUNCS([ \
BN_is_prime_ex \
DSA_generate_parameters_ex \
- EVP_DigestInit_ex \
+ EVP_CIPHER_CTX_ctrl \
EVP_DigestFinal_ex \
- EVP_MD_CTX_init \
+ EVP_DigestInit_ex \
EVP_MD_CTX_cleanup \
EVP_MD_CTX_copy_ex \
+ EVP_MD_CTX_init \
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \
])
+ # OpenSSL_add_all_algorithms may be a macro.
+ AC_CHECK_FUNC(OpenSSL_add_all_algorithms,
+ AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a function]),
+ AC_CHECK_DECL(OpenSSL_add_all_algorithms,
+ AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a macro]), ,
+ [[#include <openssl/evp.h>]]
+ )
+ )
+
+ # LibreSSL/OpenSSL 1.1x API
+ AC_CHECK_FUNCS([ \
+ OPENSSL_init_crypto \
+ DH_get0_key \
+ DH_get0_pqg \
+ DH_set0_key \
+ DH_set_length \
+ DH_set0_pqg \
+ DSA_get0_key \
+ DSA_get0_pqg \
+ DSA_set0_key \
+ DSA_set0_pqg \
+ DSA_SIG_get0 \
+ DSA_SIG_set0 \
+ ECDSA_SIG_get0 \
+ ECDSA_SIG_set0 \
+ EVP_CIPHER_CTX_iv \
+ EVP_CIPHER_CTX_iv_noconst \
+ EVP_CIPHER_CTX_get_iv \
+ EVP_CIPHER_CTX_set_iv \
+ RSA_get0_crt_params \
+ RSA_get0_factors \
+ RSA_get0_key \
+ RSA_set0_crt_params \
+ RSA_set0_factors \
+ RSA_set0_key \
+ RSA_meth_free \
+ RSA_meth_dup \
+ RSA_meth_set1_name \
+ RSA_meth_get_finish \
+ RSA_meth_set_priv_enc \
+ RSA_meth_set_priv_dec \
+ RSA_meth_set_finish \
+ EVP_PKEY_get0_RSA \
+ EVP_MD_CTX_new \
+ EVP_MD_CTX_free \
+ ])
+
if test "x$openssl_engine" = "xyes" ; then
AC_MSG_CHECKING([for OpenSSL ENGINE support])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <openssl/engine.h>
]], [[
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([USE_OPENSSL_ENGINE], [1],
[Enable OpenSSL engine support])
], [ AC_MSG_ERROR([OpenSSL ENGINE support not found])
])
fi
# Check for OpenSSL without EVP_aes_{192,256}_cbc
AC_MSG_CHECKING([whether OpenSSL has crippled AES support])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/evp.h>
]], [[
exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL);
]])],
[
AC_MSG_RESULT([no])
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([OPENSSL_LOBOTOMISED_AES], [1],
[libcrypto is missing AES 192 and 256 bit functions])
]
)
# Check for OpenSSL with EVP_aes_*ctr
AC_MSG_CHECKING([whether OpenSSL has AES CTR via EVP])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/evp.h>
]], [[
exit(EVP_aes_128_ctr() == NULL ||
EVP_aes_192_cbc() == NULL ||
EVP_aes_256_cbc() == NULL);
]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE([OPENSSL_HAVE_EVPCTR], [1],
[libcrypto has EVP AES CTR])
],
[
AC_MSG_RESULT([no])
]
)
# Check for OpenSSL with EVP_aes_*gcm
AC_MSG_CHECKING([whether OpenSSL has AES GCM via EVP])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/evp.h>
]], [[
exit(EVP_aes_128_gcm() == NULL ||
EVP_aes_256_gcm() == NULL ||
EVP_CTRL_GCM_SET_IV_FIXED == 0 ||
EVP_CTRL_GCM_IV_GEN == 0 ||
EVP_CTRL_GCM_SET_TAG == 0 ||
EVP_CTRL_GCM_GET_TAG == 0 ||
EVP_CIPHER_CTX_ctrl(NULL, 0, 0, NULL) == 0);
]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE([OPENSSL_HAVE_EVPGCM], [1],
[libcrypto has EVP AES GCM])
],
[
AC_MSG_RESULT([no])
unsupported_algorithms="$unsupported_cipers \
aes128-gcm@openssh.com \
aes256-gcm@openssh.com"
]
)
- AC_SEARCH_LIBS([EVP_CIPHER_CTX_ctrl], [crypto],
- [AC_DEFINE([HAVE_EVP_CIPHER_CTX_CTRL], [1],
- [Define if libcrypto has EVP_CIPHER_CTX_ctrl])])
-
- # LibreSSL/OpenSSL 1.1x API
- AC_SEARCH_LIBS([DH_get0_key], [crypto],
- [AC_DEFINE([HAVE_DH_GET0_KEY], [1],
- [Define if libcrypto has DH_get0_key])])
- AC_SEARCH_LIBS([DH_get0_pqg], [crypto],
- [AC_DEFINE([HAVE_DH_GET0_PQG], [1],
- [Define if libcrypto has DH_get0_pqg])])
- AC_SEARCH_LIBS([DH_set0_key], [crypto],
- [AC_DEFINE([HAVE_DH_SET0_KEY], [1],
- [Define if libcrypto has DH_set0_key])])
- AC_SEARCH_LIBS([DH_set_length], [crypto],
- [AC_DEFINE([HAVE_DH_SET_LENGTH], [1],
- [Define if libcrypto has DH_set_length])])
- AC_SEARCH_LIBS([DH_set0_pqg], [crypto],
- [AC_DEFINE([HAVE_DH_SET0_PQG], [1],
- [Define if libcrypto has DH_set0_pqg])])
-
- AC_SEARCH_LIBS([DSA_get0_key], [crypto],
- [AC_DEFINE([HAVE_DSA_GET0_KEY], [1],
- [Define if libcrypto has DSA_get0_key])])
- AC_SEARCH_LIBS([DSA_get0_pqg], [crypto],
- [AC_DEFINE([HAVE_DSA_GET0_PQG], [1],
- [Define if libcrypto has DSA_get0_pqg])])
- AC_SEARCH_LIBS([DSA_set0_key], [crypto],
- [AC_DEFINE([HAVE_DSA_SET0_KEY], [1],
- [Define if libcrypto has DSA_set0_key])])
- AC_SEARCH_LIBS([DSA_set0_pqg], [crypto],
- [AC_DEFINE([HAVE_DSA_SET0_PQG], [1],
- [Define if libcrypto has DSA_set0_pqg])])
-
- AC_SEARCH_LIBS([DSA_SIG_get0], [crypto],
- [AC_DEFINE([HAVE_DSA_SIG_GET0], [1],
- [Define if libcrypto has DSA_SIG_get0])])
- AC_SEARCH_LIBS([DSA_SIG_set0], [crypto],
- [AC_DEFINE([HAVE_DSA_SIG_SET0], [1],
- [Define if libcrypto has DSA_SIG_set0])])
-
- AC_SEARCH_LIBS([ECDSA_SIG_get0], [crypto],
- [AC_DEFINE([HAVE_ECDSA_SIG_GET0], [1],
- [Define if libcrypto has ECDSA_SIG_get0])])
- AC_SEARCH_LIBS([ECDSA_SIG_set0], [crypto],
- [AC_DEFINE([HAVE_ECDSA_SIG_SET0], [1],
- [Define if libcrypto has ECDSA_SIG_set0])])
-
- AC_SEARCH_LIBS([EVP_CIPHER_CTX_iv], [crypto],
- [AC_DEFINE([HAVE_EVP_CIPHER_CTX_IV], [1],
- [Define if libcrypto has EVP_CIPHER_CTX_iv])])
- AC_SEARCH_LIBS([EVP_CIPHER_CTX_iv_noconst], [crypto],
- [AC_DEFINE([HAVE_EVP_CIPHER_CTX_IV_NOCONST], [1],
- [Define if libcrypto has EVP_CIPHER_CTX_iv_noconst])])
- AC_SEARCH_LIBS([EVP_CIPHER_CTX_get_iv], [crypto],
- [AC_DEFINE([HAVE_EVP_CIPHER_CTX_GET_IV], [1],
- [Define if libcrypto has EVP_CIPHER_CTX_get_iv])])
- AC_SEARCH_LIBS([EVP_CIPHER_CTX_set_iv], [crypto],
- [AC_DEFINE([HAVE_EVP_CIPHER_CTX_GET_IV], [1],
- [Define if libcrypto has EVP_CIPHER_CTX_set_iv])])
-
- AC_SEARCH_LIBS([RSA_get0_crt_params], [crypto],
- [AC_DEFINE([HAVE_RSA_GET0_CRT_PARAMS], [1],
- [Define if libcrypto has RSA_get0_crt_params])])
- AC_SEARCH_LIBS([RSA_get0_factors], [crypto],
- [AC_DEFINE([HAVE_RSA_GET0_FACTORS], [1],
- [Define if libcrypto has RSA_get0_factors])])
- AC_SEARCH_LIBS([RSA_get0_key], [crypto],
- [AC_DEFINE([HAVE_RSA_GET0_KEY], [1],
- [Define if libcrypto has RSA_get0_key])])
- AC_SEARCH_LIBS([RSA_set0_crt_params], [crypto],
- [AC_DEFINE([HAVE_RSA_SET0_CRT_PARAMS], [1],
- [Define if libcrypto has RSA_get0_srt_params])])
- AC_SEARCH_LIBS([RSA_set0_factors], [crypto],
- [AC_DEFINE([HAVE_RSA_SET0_FACTORS], [1],
- [Define if libcrypto has RSA_set0_factors])])
- AC_SEARCH_LIBS([RSA_set0_key], [crypto],
- [AC_DEFINE([HAVE_RSA_SET0_KEY], [1],
- [Define if libcrypto has RSA_set0_key])])
-
- AC_SEARCH_LIBS([RSA_meth_free], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_FREE], [1],
- [Define if libcrypto has RSA_meth_free])])
- AC_SEARCH_LIBS([RSA_meth_dup], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_DUP], [1],
- [Define if libcrypto has RSA_meth_dup])])
- AC_SEARCH_LIBS([RSA_meth_set1_name], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_SET1_NAME], [1],
- [Define if libcrypto has RSA_meth_set1_name])])
- AC_SEARCH_LIBS([RSA_meth_get_finish], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_GET_FINISH], [1],
- [Define if libcrypto has RSA_meth_get_finish])])
- AC_SEARCH_LIBS([RSA_meth_set_priv_enc], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_SET_PRIV_ENC], [1],
- [Define if libcrypto has RSA_meth_set_priv_enc])])
- AC_SEARCH_LIBS([RSA_meth_set_priv_dec], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_SET_PRIV_DEC], [1],
- [Define if libcrypto has RSA_meth_set_priv_dec])])
- AC_SEARCH_LIBS([RSA_meth_set_finish], [crypto],
- [AC_DEFINE([HAVE_RSA_METH_SET_FINISH], [1],
- [Define if libcrypto has RSA_meth_set_finish])])
-
- AC_SEARCH_LIBS([EVP_PKEY_get0_RSA], [crypto],
- [AC_DEFINE([HAVE_EVP_PKEY_GET0_RSA], [1],
- [Define if libcrypto has EVP_PKEY_get0_RSA])])
-
- AC_SEARCH_LIBS([EVP_MD_CTX_new], [crypto],
- [AC_DEFINE([HAVE_EVP_MD_CTX_NEW], [1],
- [Define if libcrypto has EVP_MD_CTX_new])])
- AC_SEARCH_LIBS([EVP_MD_CTX_free], [crypto],
- [AC_DEFINE([HAVE_EVP_MD_CTX_FREE], [1],
- [Define if libcrypto has EVP_MD_CTX_free])])
-
AC_MSG_CHECKING([if EVP_DigestUpdate returns an int])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/evp.h>
]], [[
if(EVP_DigestUpdate(NULL, NULL,0))
exit(0);
]])],
[
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1],
[Define if EVP_DigestUpdate returns void])
]
)
# Some systems want crypt() from libcrypt, *not* the version in OpenSSL,
# because the system crypt() is more featureful.
if test "x$check_for_libcrypt_before" = "x1"; then
AC_CHECK_LIB([crypt], [crypt])
fi
# Some Linux systems (Slackware) need crypt() from libcrypt, *not* the
# version in OpenSSL.
if test "x$check_for_libcrypt_later" = "x1"; then
AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"])
fi
AC_CHECK_FUNCS([crypt DES_crypt])
# Search for SHA256 support in libc and/or OpenSSL
AC_CHECK_FUNCS([SHA256_Update EVP_sha256], ,
[unsupported_algorithms="$unsupported_algorithms \
hmac-sha2-256 \
hmac-sha2-512 \
diffie-hellman-group-exchange-sha256 \
hmac-sha2-256-etm@openssh.com \
hmac-sha2-512-etm@openssh.com"
]
)
# Search for RIPE-MD support in OpenSSL
AC_CHECK_FUNCS([EVP_ripemd160], ,
[unsupported_algorithms="$unsupported_algorithms \
hmac-ripemd160 \
hmac-ripemd160@openssh.com \
hmac-ripemd160-etm@openssh.com"
]
)
# Check complete ECC support in OpenSSL
AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
]], [[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
const EVP_MD *m = EVP_sha256(); /* We need this too */
]])],
[ AC_MSG_RESULT([yes])
enable_nistp256=1 ],
[ AC_MSG_RESULT([no]) ]
)
AC_MSG_CHECKING([whether OpenSSL has NID_secp384r1])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
]], [[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1);
const EVP_MD *m = EVP_sha384(); /* We need this too */
]])],
[ AC_MSG_RESULT([yes])
enable_nistp384=1 ],
[ AC_MSG_RESULT([no]) ]
)
AC_MSG_CHECKING([whether OpenSSL has NID_secp521r1])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
]], [[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
const EVP_MD *m = EVP_sha512(); /* We need this too */
]])],
[ AC_MSG_RESULT([yes])
AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/opensslv.h>
]],[[
EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1);
const EVP_MD *m = EVP_sha512(); /* We need this too */
exit(e == NULL || m == NULL);
]])],
[ AC_MSG_RESULT([yes])
enable_nistp521=1 ],
[ AC_MSG_RESULT([no]) ],
[ AC_MSG_WARN([cross-compiling: assuming yes])
enable_nistp521=1 ]
)],
AC_MSG_RESULT([no])
)
COMMENT_OUT_ECC="#no ecc#"
TEST_SSH_ECC=no
if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \
test x$enable_nistp521 = x1; then
AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC])
+ AC_CHECK_FUNCS([EC_KEY_METHOD_new])
fi
if test x$enable_nistp256 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP256], [1],
[libcrypto has NID_X9_62_prime256v1])
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdsa-sha2-nistp256 \
ecdh-sha2-nistp256 \
ecdsa-sha2-nistp256-cert-v01@openssh.com"
fi
if test x$enable_nistp384 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1])
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdsa-sha2-nistp384 \
ecdh-sha2-nistp384 \
ecdsa-sha2-nistp384-cert-v01@openssh.com"
fi
if test x$enable_nistp521 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1])
TEST_SSH_ECC=yes
COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdh-sha2-nistp521 \
ecdsa-sha2-nistp521 \
ecdsa-sha2-nistp521-cert-v01@openssh.com"
fi
AC_SUBST([TEST_SSH_ECC])
AC_SUBST([COMMENT_OUT_ECC])
else
AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"])
AC_CHECK_FUNCS([crypt])
fi
AC_CHECK_FUNCS([ \
arc4random \
arc4random_buf \
arc4random_stir \
arc4random_uniform \
])
saved_LIBS="$LIBS"
AC_CHECK_LIB([iaf], [ia_openinfo], [
LIBS="$LIBS -liaf"
AC_CHECK_FUNCS([set_id], [SSHDLIBS="$SSHDLIBS -liaf"
AC_DEFINE([HAVE_LIBIAF], [1],
[Define if system has libiaf that supports set_id])
])
])
LIBS="$saved_LIBS"
### Configure cryptographic random number support
# Check whether OpenSSL seeds itself
if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <string.h>
#include <openssl/rand.h>
]], [[
exit(RAND_status() == 1 ? 0 : 1);
]])],
[
OPENSSL_SEEDS_ITSELF=yes
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
],
[
AC_MSG_WARN([cross compiling: assuming yes])
# This is safe, since we will fatal() at runtime if
# OpenSSL is not seeded correctly.
OPENSSL_SEEDS_ITSELF=yes
]
)
fi
# PRNGD TCP socket
AC_ARG_WITH([prngd-port],
[ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT],
[
case "$withval" in
no)
withval=""
;;
[[0-9]]*)
;;
*)
AC_MSG_ERROR([You must specify a numeric port number for --with-prngd-port])
;;
esac
if test ! -z "$withval" ; then
PRNGD_PORT="$withval"
AC_DEFINE_UNQUOTED([PRNGD_PORT], [$PRNGD_PORT],
[Port number of PRNGD/EGD random number socket])
fi
]
)
# PRNGD Unix domain socket
AC_ARG_WITH([prngd-socket],
[ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)],
[
case "$withval" in
yes)
withval="/var/run/egd-pool"
;;
no)
withval=""
;;
/*)
;;
*)
AC_MSG_ERROR([You must specify an absolute path to the entropy socket])
;;
esac
if test ! -z "$withval" ; then
if test ! -z "$PRNGD_PORT" ; then
AC_MSG_ERROR([You may not specify both a PRNGD/EGD port and socket])
fi
if test ! -r "$withval" ; then
AC_MSG_WARN([Entropy socket is not readable])
fi
PRNGD_SOCKET="$withval"
AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"],
[Location of PRNGD/EGD random number socket])
fi
],
[
# Check for existing socket only if we don't have a random device already
if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then
AC_MSG_CHECKING([for PRNGD/EGD socket])
# Insert other locations here
for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do
if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then
PRNGD_SOCKET="$sock"
AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"])
break;
fi
done
if test ! -z "$PRNGD_SOCKET" ; then
AC_MSG_RESULT([$PRNGD_SOCKET])
else
AC_MSG_RESULT([not found])
fi
fi
]
)
# Which randomness source do we use?
if test ! -z "$PRNGD_PORT" ; then
RAND_MSG="PRNGd port $PRNGD_PORT"
elif test ! -z "$PRNGD_SOCKET" ; then
RAND_MSG="PRNGd socket $PRNGD_SOCKET"
elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then
AC_DEFINE([OPENSSL_PRNG_ONLY], [1],
[Define if you want the OpenSSL internally seeded PRNG only])
RAND_MSG="OpenSSL internal ONLY"
elif test "x$openssl" = "xno" ; then
AC_MSG_WARN([OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible])
else
AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options])
fi
# Check for PAM libs
PAM_MSG="no"
AC_ARG_WITH([pam],
[ --with-pam Enable PAM support ],
[
if test "x$withval" != "xno" ; then
if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
AC_MSG_ERROR([PAM headers not found])
fi
saved_LIBS="$LIBS"
AC_CHECK_LIB([dl], [dlopen], , )
AC_CHECK_LIB([pam], [pam_set_item], , [AC_MSG_ERROR([*** libpam missing])])
AC_CHECK_FUNCS([pam_getenvlist])
AC_CHECK_FUNCS([pam_putenv])
LIBS="$saved_LIBS"
PAM_MSG="yes"
SSHDLIBS="$SSHDLIBS -lpam"
AC_DEFINE([USE_PAM], [1],
[Define if you want to enable PAM support])
if test $ac_cv_lib_dl_dlopen = yes; then
case "$LIBS" in
*-ldl*)
# libdl already in LIBS
;;
*)
SSHDLIBS="$SSHDLIBS -ldl"
;;
esac
fi
fi
]
)
AC_ARG_WITH([pam-service],
[ --with-pam-service=name Specify PAM service name ],
[
if test "x$withval" != "xno" && \
test "x$withval" != "xyes" ; then
AC_DEFINE_UNQUOTED([SSHD_PAM_SERVICE],
["$withval"], [sshd PAM service name])
fi
]
)
# Check for older PAM
if test "x$PAM_MSG" = "xyes" ; then
# Check PAM strerror arguments (old PAM)
AC_MSG_CHECKING([whether pam_strerror takes only one argument])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <stdlib.h>
#if defined(HAVE_SECURITY_PAM_APPL_H)
#include <security/pam_appl.h>
#elif defined (HAVE_PAM_PAM_APPL_H)
#include <pam/pam_appl.h>
#endif
]], [[
(void)pam_strerror((pam_handle_t *)NULL, -1);
]])], [AC_MSG_RESULT([no])], [
AC_DEFINE([HAVE_OLD_PAM], [1],
[Define if you have an old version of PAM
which takes only one argument to pam_strerror])
AC_MSG_RESULT([yes])
PAM_MSG="yes (old library)"
])
fi
case "$host" in
*-*-cygwin*)
SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER
;;
*)
SSH_PRIVSEP_USER=sshd
;;
esac
AC_ARG_WITH([privsep-user],
[ --with-privsep-user=user Specify non-privileged user for privilege separation],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
SSH_PRIVSEP_USER=$withval
fi
]
)
if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then
AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], [CYGWIN_SSH_PRIVSEP_USER],
[Cygwin function to fetch non-privileged user for privilege separation])
else
AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"],
[non-privileged user for privilege separation])
fi
AC_SUBST([SSH_PRIVSEP_USER])
if test "x$have_linux_no_new_privs" = "x1" ; then
AC_CHECK_DECL([SECCOMP_MODE_FILTER], [have_seccomp_filter=1], , [
#include <sys/types.h>
#include <linux/seccomp.h>
])
fi
if test "x$have_seccomp_filter" = "x1" ; then
AC_MSG_CHECKING([kernel for seccomp_filter support])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <errno.h>
#include <elf.h>
#include <linux/audit.h>
#include <linux/seccomp.h>
#include <stdlib.h>
#include <sys/prctl.h>
]],
[[ int i = $seccomp_audit_arch;
errno = 0;
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0);
exit(errno == EFAULT ? 0 : 1); ]])],
[ AC_MSG_RESULT([yes]) ], [
AC_MSG_RESULT([no])
# Disable seccomp filter as a target
have_seccomp_filter=0
]
)
fi
# Decide which sandbox style to use
sandbox_arg=""
AC_ARG_WITH([sandbox],
[ --with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter, systrace, pledge)],
[
if test "x$withval" = "xyes" ; then
sandbox_arg=""
else
sandbox_arg="$withval"
fi
]
)
# Some platforms (seems to be the ones that have a kernel poll(2)-type
# function with which they implement select(2)) use an extra file descriptor
# when calling select(2), which means we can't use the rlimit sandbox.
AC_MSG_CHECKING([if select works with descriptor rlimit])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/resource.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
]],[[
struct rlimit rl_zero;
int fd, r;
fd_set fds;
struct timeval tv;
fd = open("/dev/null", O_RDONLY);
FD_ZERO(&fds);
FD_SET(fd, &fds);
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
setrlimit(RLIMIT_FSIZE, &rl_zero);
setrlimit(RLIMIT_NOFILE, &rl_zero);
tv.tv_sec = 1;
tv.tv_usec = 0;
r = select(fd+1, &fds, NULL, NULL, &tv);
exit (r == -1 ? 1 : 0);
]])],
[AC_MSG_RESULT([yes])
select_works_with_rlimit=yes],
[AC_MSG_RESULT([no])
select_works_with_rlimit=no],
[AC_MSG_WARN([cross compiling: assuming yes])
select_works_with_rlimit=yes]
)
AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/resource.h>
#include <errno.h>
#include <stdlib.h>
]],[[
struct rlimit rl_zero;
int fd, r;
fd_set fds;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
r = setrlimit(RLIMIT_NOFILE, &rl_zero);
exit (r == -1 ? 1 : 0);
]])],
[AC_MSG_RESULT([yes])
rlimit_nofile_zero_works=yes],
[AC_MSG_RESULT([no])
rlimit_nofile_zero_works=no],
[AC_MSG_WARN([cross compiling: assuming yes])
rlimit_nofile_zero_works=yes]
)
AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/resource.h>
#include <stdlib.h>
]],[[
struct rlimit rl_zero;
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0);
]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_DEFINE(SANDBOX_SKIP_RLIMIT_FSIZE, 1,
[setrlimit RLIMIT_FSIZE works])],
[AC_MSG_WARN([cross compiling: assuming yes])]
)
if test "x$sandbox_arg" = "xpledge" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_pledge" = "xyes" ) ; then
test "x$ac_cv_func_pledge" != "xyes" && \
AC_MSG_ERROR([pledge sandbox requires pledge(2) support])
SANDBOX_STYLE="pledge"
AC_DEFINE([SANDBOX_PLEDGE], [1], [Sandbox using pledge(2)])
elif test "x$sandbox_arg" = "xsystrace" || \
( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then
test "x$have_systr_policy_kill" != "x1" && \
AC_MSG_ERROR([systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support])
SANDBOX_STYLE="systrace"
AC_DEFINE([SANDBOX_SYSTRACE], [1], [Sandbox using systrace(4)])
elif test "x$sandbox_arg" = "xdarwin" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \
test "x$ac_cv_header_sandbox_h" = "xyes") ; then
test "x$ac_cv_func_sandbox_init" != "xyes" -o \
"x$ac_cv_header_sandbox_h" != "xyes" && \
AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function])
SANDBOX_STYLE="darwin"
AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)])
elif test "x$sandbox_arg" = "xseccomp_filter" || \
( test -z "$sandbox_arg" && \
test "x$have_seccomp_filter" = "x1" && \
test "x$ac_cv_header_elf_h" = "xyes" && \
test "x$ac_cv_header_linux_audit_h" = "xyes" && \
test "x$ac_cv_header_linux_filter_h" = "xyes" && \
test "x$seccomp_audit_arch" != "x" && \
test "x$have_linux_no_new_privs" = "x1" && \
test "x$ac_cv_func_prctl" = "xyes" ) ; then
test "x$seccomp_audit_arch" = "x" && \
AC_MSG_ERROR([seccomp_filter sandbox not supported on $host])
test "x$have_linux_no_new_privs" != "x1" && \
AC_MSG_ERROR([seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS])
test "x$have_seccomp_filter" != "x1" && \
AC_MSG_ERROR([seccomp_filter sandbox requires seccomp headers])
test "x$ac_cv_func_prctl" != "xyes" && \
AC_MSG_ERROR([seccomp_filter sandbox requires prctl function])
SANDBOX_STYLE="seccomp_filter"
AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter])
elif test "x$sandbox_arg" = "xcapsicum" || \
( test -z "$sandbox_arg" && \
test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \
test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header])
test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function])
SANDBOX_STYLE="capsicum"
AC_DEFINE([SANDBOX_CAPSICUM], [1], [Sandbox using capsicum])
elif test "x$sandbox_arg" = "xrlimit" || \
( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \
test "x$select_works_with_rlimit" = "xyes" && \
test "x$rlimit_nofile_zero_works" = "xyes" ) ; then
test "x$ac_cv_func_setrlimit" != "xyes" && \
AC_MSG_ERROR([rlimit sandbox requires setrlimit function])
test "x$select_works_with_rlimit" != "xyes" && \
AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit])
SANDBOX_STYLE="rlimit"
AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)])
elif test "x$sandbox_arg" = "xsolaris" || \
( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then
SANDBOX_STYLE="solaris"
AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges])
elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \
test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then
SANDBOX_STYLE="none"
AC_DEFINE([SANDBOX_NULL], [1], [no privsep sandboxing])
else
AC_MSG_ERROR([unsupported --with-sandbox])
fi
# Cheap hack to ensure NEWS-OS libraries are arranged right.
if test ! -z "$SONY" ; then
LIBS="$LIBS -liberty";
fi
# Check for long long datatypes
AC_CHECK_TYPES([long long, unsigned long long, long double])
# Check datatype sizes
-AC_CHECK_SIZEOF([short int], [2])
-AC_CHECK_SIZEOF([int], [4])
-AC_CHECK_SIZEOF([long int], [4])
-AC_CHECK_SIZEOF([long long int], [8])
+AC_CHECK_SIZEOF([short int])
+AC_CHECK_SIZEOF([int])
+AC_CHECK_SIZEOF([long int])
+AC_CHECK_SIZEOF([long long int])
# Sanity check long long for some platforms (AIX)
if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
ac_cv_sizeof_long_long_int=0
fi
# compute LLONG_MIN and LLONG_MAX if we don't know them.
if test -z "$have_llong_max"; then
AC_MSG_CHECKING([for max value of long long])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
/* Why is this so damn hard? */
#ifdef __GNUC__
# undef __GNUC__
#endif
#define __USE_ISOC99
#include <limits.h>
#define DATA "conftest.llminmax"
#define my_abs(a) ((a) < 0 ? ((a) * -1) : (a))
/*
* printf in libc on some platforms (eg old Tru64) does not understand %lld so
* we do this the hard way.
*/
static int
fprint_ll(FILE *f, long long n)
{
unsigned int i;
int l[sizeof(long long) * 8];
if (n < 0)
if (fprintf(f, "-") < 0)
return -1;
for (i = 0; n != 0; i++) {
l[i] = my_abs(n % 10);
n /= 10;
}
do {
if (fprintf(f, "%d", l[--i]) < 0)
return -1;
} while (i != 0);
if (fprintf(f, " ") < 0)
return -1;
return 0;
}
]], [[
FILE *f;
long long i, llmin, llmax = 0;
if((f = fopen(DATA,"w")) == NULL)
exit(1);
#if defined(LLONG_MIN) && defined(LLONG_MAX)
fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n");
llmin = LLONG_MIN;
llmax = LLONG_MAX;
#else
fprintf(stderr, "Calculating LLONG_MIN and LLONG_MAX\n");
/* This will work on one's complement and two's complement */
for (i = 1; i > llmax; i <<= 1, i++)
llmax = i;
llmin = llmax + 1LL; /* wrap */
#endif
/* Sanity check */
if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax
|| llmax - 1 > llmax || llmin == llmax || llmin == 0
|| llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) {
fprintf(f, "unknown unknown\n");
exit(2);
}
if (fprint_ll(f, llmin) < 0)
exit(3);
if (fprint_ll(f, llmax) < 0)
exit(4);
if (fclose(f) < 0)
exit(5);
exit(0);
]])],
[
llong_min=`$AWK '{print $1}' conftest.llminmax`
llong_max=`$AWK '{print $2}' conftest.llminmax`
AC_MSG_RESULT([$llong_max])
AC_DEFINE_UNQUOTED([LLONG_MAX], [${llong_max}LL],
[max value of long long calculated by configure])
AC_MSG_CHECKING([for min value of long long])
AC_MSG_RESULT([$llong_min])
AC_DEFINE_UNQUOTED([LLONG_MIN], [${llong_min}LL],
[min value of long long calculated by configure])
],
[
AC_MSG_RESULT([not found])
],
[
AC_MSG_WARN([cross compiling: not checking])
]
)
fi
# More checks for data types
AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_int a; a = 1;]])],
[ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no"
])
])
if test "x$ac_cv_have_u_int" = "xyes" ; then
AC_DEFINE([HAVE_U_INT], [1], [define if you have u_int data type])
have_u_int=1
fi
AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])],
[ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no"
])
])
if test "x$ac_cv_have_intxx_t" = "xyes" ; then
AC_DEFINE([HAVE_INTXX_T], [1], [define if you have intxx_t data type])
have_intxx_t=1
fi
if (test -z "$have_intxx_t" && \
test "x$ac_cv_header_stdint_h" = "xyes")
then
AC_MSG_CHECKING([for intXX_t types in stdint.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdint.h> ]],
[[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])],
[
AC_DEFINE([HAVE_INTXX_T])
AC_MSG_RESULT([yes])
], [ AC_MSG_RESULT([no])
])
fi
AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <sys/socket.h>
#ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h>
#endif
]], [[
int64_t a; a = 1;
]])],
[ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no"
])
])
if test "x$ac_cv_have_int64_t" = "xyes" ; then
AC_DEFINE([HAVE_INT64_T], [1], [define if you have int64_t data type])
fi
AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])],
[ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no"
])
])
if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then
AC_DEFINE([HAVE_U_INTXX_T], [1], [define if you have u_intxx_t data type])
have_u_intxx_t=1
fi
if test -z "$have_u_intxx_t" ; then
AC_MSG_CHECKING([for u_intXX_t types in sys/socket.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/socket.h> ]],
[[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])],
[
AC_DEFINE([HAVE_U_INTXX_T])
AC_MSG_RESULT([yes])
], [ AC_MSG_RESULT([no])
])
fi
AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_int64_t a; a = 1;]])],
[ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no"
])
])
if test "x$ac_cv_have_u_int64_t" = "xyes" ; then
AC_DEFINE([HAVE_U_INT64_T], [1], [define if you have u_int64_t data type])
have_u_int64_t=1
fi
if (test -z "$have_u_int64_t" && \
test "x$ac_cv_header_sys_bitypes_h" = "xyes")
then
AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/bitypes.h> ]],
[[ u_int64_t a; a = 1]])],
[
AC_DEFINE([HAVE_U_INT64_T])
AC_MSG_RESULT([yes])
], [ AC_MSG_RESULT([no])
])
fi
if test -z "$have_u_intxx_t" ; then
AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
]], [[
uint8_t a;
uint16_t b;
uint32_t c;
a = b = c = 1;
]])],
[ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no"
])
])
if test "x$ac_cv_have_uintxx_t" = "xyes" ; then
AC_DEFINE([HAVE_UINTXX_T], [1],
[define if you have uintxx_t data type])
fi
fi
if (test -z "$have_uintxx_t" && \
test "x$ac_cv_header_stdint_h" = "xyes")
then
AC_MSG_CHECKING([for uintXX_t types in stdint.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdint.h> ]],
[[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])],
[
AC_DEFINE([HAVE_UINTXX_T])
AC_MSG_RESULT([yes])
], [ AC_MSG_RESULT([no])
])
fi
if (test -z "$have_uintxx_t" && \
test "x$ac_cv_header_inttypes_h" = "xyes")
then
AC_MSG_CHECKING([for uintXX_t types in inttypes.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <inttypes.h> ]],
[[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])],
[
AC_DEFINE([HAVE_UINTXX_T])
AC_MSG_RESULT([yes])
], [ AC_MSG_RESULT([no])
])
fi
if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \
test "x$ac_cv_header_sys_bitypes_h" = "xyes")
then
AC_MSG_CHECKING([for intXX_t and u_intXX_t types in sys/bitypes.h])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/bitypes.h>
]], [[
int8_t a; int16_t b; int32_t c;
u_int8_t e; u_int16_t f; u_int32_t g;
a = b = c = e = f = g = 1;
]])],
[
AC_DEFINE([HAVE_U_INTXX_T])
AC_DEFINE([HAVE_INTXX_T])
AC_MSG_RESULT([yes])
], [AC_MSG_RESULT([no])
])
fi
AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ u_char foo; foo = 125; ]])],
[ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no"
])
])
if test "x$ac_cv_have_u_char" = "xyes" ; then
AC_DEFINE([HAVE_U_CHAR], [1], [define if you have u_char data type])
fi
AC_CHECK_TYPES([intmax_t, uintmax_t], , , [
#include <sys/types.h>
#include <stdint.h>
])
TYPE_SOCKLEN_T
AC_CHECK_TYPES([sig_atomic_t], , , [#include <signal.h>])
AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
])
AC_CHECK_MEMBERS([struct statfs.f_flags], [], [], [[
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
#include <sys/bitypes.h>
#endif
#ifdef HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
#endif
]])
AC_CHECK_TYPES([in_addr_t, in_port_t], , ,
[#include <sys/types.h>
#include <netinet/in.h>])
AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ size_t foo; foo = 1235; ]])],
[ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no"
])
])
if test "x$ac_cv_have_size_t" = "xyes" ; then
AC_DEFINE([HAVE_SIZE_T], [1], [define if you have size_t data type])
fi
AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ ssize_t foo; foo = 1235; ]])],
[ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no"
])
])
if test "x$ac_cv_have_ssize_t" = "xyes" ; then
AC_DEFINE([HAVE_SSIZE_T], [1], [define if you have ssize_t data type])
fi
AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <time.h> ]],
[[ clock_t foo; foo = 1235; ]])],
[ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no"
])
])
if test "x$ac_cv_have_clock_t" = "xyes" ; then
AC_DEFINE([HAVE_CLOCK_T], [1], [define if you have clock_t data type])
fi
AC_CACHE_CHECK([for sa_family_t], ac_cv_have_sa_family_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
]], [[ sa_family_t foo; foo = 1235; ]])],
[ ac_cv_have_sa_family_t="yes" ],
[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
]], [[ sa_family_t foo; foo = 1235; ]])],
[ ac_cv_have_sa_family_t="yes" ],
[ ac_cv_have_sa_family_t="no" ]
)
])
])
if test "x$ac_cv_have_sa_family_t" = "xyes" ; then
AC_DEFINE([HAVE_SA_FAMILY_T], [1],
[define if you have sa_family_t data type])
fi
AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ pid_t foo; foo = 1235; ]])],
[ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no"
])
])
if test "x$ac_cv_have_pid_t" = "xyes" ; then
AC_DEFINE([HAVE_PID_T], [1], [define if you have pid_t data type])
fi
AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/types.h> ]],
[[ mode_t foo; foo = 1235; ]])],
[ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no"
])
])
if test "x$ac_cv_have_mode_t" = "xyes" ; then
AC_DEFINE([HAVE_MODE_T], [1], [define if you have mode_t data type])
fi
AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
]], [[ struct sockaddr_storage s; ]])],
[ ac_cv_have_struct_sockaddr_storage="yes" ],
[ ac_cv_have_struct_sockaddr_storage="no"
])
])
if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then
AC_DEFINE([HAVE_STRUCT_SOCKADDR_STORAGE], [1],
[define if you have struct sockaddr_storage data type])
fi
AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <netinet/in.h>
]], [[ struct sockaddr_in6 s; s.sin6_family = 0; ]])],
[ ac_cv_have_struct_sockaddr_in6="yes" ],
[ ac_cv_have_struct_sockaddr_in6="no"
])
])
if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then
AC_DEFINE([HAVE_STRUCT_SOCKADDR_IN6], [1],
[define if you have struct sockaddr_in6 data type])
fi
AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <netinet/in.h>
]], [[ struct in6_addr s; s.s6_addr[0] = 0; ]])],
[ ac_cv_have_struct_in6_addr="yes" ],
[ ac_cv_have_struct_in6_addr="no"
])
])
if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then
AC_DEFINE([HAVE_STRUCT_IN6_ADDR], [1],
[define if you have struct in6_addr data type])
dnl Now check for sin6_scope_id
AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], , ,
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>
])
fi
AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
]], [[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ]])],
[ ac_cv_have_struct_addrinfo="yes" ],
[ ac_cv_have_struct_addrinfo="no"
])
])
if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
AC_DEFINE([HAVE_STRUCT_ADDRINFO], [1],
[define if you have struct addrinfo data type])
fi
AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/time.h> ]],
[[ struct timeval tv; tv.tv_sec = 1;]])],
[ ac_cv_have_struct_timeval="yes" ],
[ ac_cv_have_struct_timeval="no"
])
])
if test "x$ac_cv_have_struct_timeval" = "xyes" ; then
AC_DEFINE([HAVE_STRUCT_TIMEVAL], [1], [define if you have struct timeval])
have_struct_timeval=1
fi
AC_CHECK_TYPES([struct timespec])
# We need int64_t or else certain parts of the compile will fail.
if test "x$ac_cv_have_int64_t" = "xno" && \
test "x$ac_cv_sizeof_long_int" != "x8" && \
test "x$ac_cv_sizeof_long_long_int" = "x0" ; then
echo "OpenSSH requires int64_t support. Contact your vendor or install"
echo "an alternative compiler (I.E., GCC) before continuing."
echo ""
exit 1;
else
dnl test snprintf (broken on SCO w/gcc)
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <stdio.h>
#include <string.h>
#ifdef HAVE_SNPRINTF
main()
{
char buf[50];
char expected_out[50];
int mazsize = 50 ;
#if (SIZEOF_LONG_INT == 8)
long int num = 0x7fffffffffffffff;
#else
long long num = 0x7fffffffffffffffll;
#endif
strcpy(expected_out, "9223372036854775807");
snprintf(buf, mazsize, "%lld", num);
if(strcmp(buf, expected_out) != 0)
exit(1);
exit(0);
}
#else
main() { exit(0); }
#endif
]])], [ true ], [ AC_DEFINE([BROKEN_SNPRINTF]) ],
AC_MSG_WARN([cross compiling: Assuming working snprintf()])
)
fi
dnl Checks for structure members
OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmp.h], [HAVE_HOST_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmpx.h], [HAVE_HOST_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([syslen], [utmpx.h], [HAVE_SYSLEN_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_pid], [utmp.h], [HAVE_PID_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmp.h], [HAVE_TYPE_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmpx.h], [HAVE_TYPE_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmp.h], [HAVE_TV_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmp.h], [HAVE_ID_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmpx.h], [HAVE_ID_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmp.h], [HAVE_ADDR_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmpx.h], [HAVE_ADDR_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmp.h], [HAVE_ADDR_V6_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmpx.h], [HAVE_ADDR_V6_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_exit], [utmp.h], [HAVE_EXIT_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmp.h], [HAVE_TIME_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX])
AC_CHECK_MEMBERS([struct stat.st_blksize])
AC_CHECK_MEMBERS([struct stat.st_mtim])
AC_CHECK_MEMBERS([struct stat.st_mtime])
AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class,
struct passwd.pw_change, struct passwd.pw_expire],
[], [], [[
#include <sys/types.h>
#include <pwd.h>
]])
AC_CHECK_MEMBER([struct __res_state.retrans], [], [AC_DEFINE([__res_state], [state],
[Define if we don't have struct __res_state in resolv.h])],
[[
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
]])
AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage],
ac_cv_have_ss_family_in_struct_ss, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
]], [[ struct sockaddr_storage s; s.ss_family = 1; ]])],
[ ac_cv_have_ss_family_in_struct_ss="yes" ],
[ ac_cv_have_ss_family_in_struct_ss="no" ])
])
if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then
AC_DEFINE([HAVE_SS_FAMILY_IN_SS], [1], [Fields in struct sockaddr_storage])
fi
AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage],
ac_cv_have___ss_family_in_struct_ss, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
]], [[ struct sockaddr_storage s; s.__ss_family = 1; ]])],
[ ac_cv_have___ss_family_in_struct_ss="yes" ],
[ ac_cv_have___ss_family_in_struct_ss="no"
])
])
if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then
AC_DEFINE([HAVE___SS_FAMILY_IN_SS], [1],
[Fields in struct sockaddr_storage])
fi
dnl make sure we're using the real structure members and not defines
AC_CACHE_CHECK([for msg_accrights field in struct msghdr],
ac_cv_have_accrights_in_msghdr, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
]], [[
#ifdef msg_accrights
#error "msg_accrights is a macro"
exit(1);
#endif
struct msghdr m;
m.msg_accrights = 0;
exit(0);
]])],
[ ac_cv_have_accrights_in_msghdr="yes" ],
[ ac_cv_have_accrights_in_msghdr="no" ]
)
])
if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then
AC_DEFINE([HAVE_ACCRIGHTS_IN_MSGHDR], [1],
[Define if your system uses access rights style
file descriptor passing])
fi
AC_MSG_CHECKING([if struct statvfs.f_fsid is integral type])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/param.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
]], [[ struct statvfs s; s.f_fsid = 0; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_MSG_CHECKING([if fsid_t has member val])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/statvfs.h>
]], [[ fsid_t t; t.val[0] = 0; ]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([FSID_HAS_VAL], [1], [fsid_t has member val]) ],
[ AC_MSG_RESULT([no]) ])
AC_MSG_CHECKING([if f_fsid has member __val])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/statvfs.h>
]], [[ fsid_t t; t.__val[0] = 0; ]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([FSID_HAS___VAL], [1], [fsid_t has member __val]) ],
[ AC_MSG_RESULT([no]) ])
])
AC_CACHE_CHECK([for msg_control field in struct msghdr],
ac_cv_have_control_in_msghdr, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
]], [[
#ifdef msg_control
#error "msg_control is a macro"
exit(1);
#endif
struct msghdr m;
m.msg_control = 0;
exit(0);
]])],
[ ac_cv_have_control_in_msghdr="yes" ],
[ ac_cv_have_control_in_msghdr="no" ]
)
])
if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then
AC_DEFINE([HAVE_CONTROL_IN_MSGHDR], [1],
[Define if your system uses ancillary data style
file descriptor passing])
fi
AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
[[ extern char *__progname; printf("%s", __progname); ]])],
[ ac_cv_libc_defines___progname="yes" ],
[ ac_cv_libc_defines___progname="no"
])
])
if test "x$ac_cv_libc_defines___progname" = "xyes" ; then
AC_DEFINE([HAVE___PROGNAME], [1], [Define if libc defines __progname])
fi
AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNCTION__, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ printf("%s", __FUNCTION__); ]])],
[ ac_cv_cc_implements___FUNCTION__="yes" ],
[ ac_cv_cc_implements___FUNCTION__="no"
])
])
if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then
AC_DEFINE([HAVE___FUNCTION__], [1],
[Define if compiler implements __FUNCTION__])
fi
AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ printf("%s", __func__); ]])],
[ ac_cv_cc_implements___func__="yes" ],
[ ac_cv_cc_implements___func__="no"
])
])
if test "x$ac_cv_cc_implements___func__" = "xyes" ; then
AC_DEFINE([HAVE___func__], [1], [Define if compiler implements __func__])
fi
AC_CACHE_CHECK([whether va_copy exists], ac_cv_have_va_copy, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdarg.h>
va_list x,y;
]], [[ va_copy(x,y); ]])],
[ ac_cv_have_va_copy="yes" ],
[ ac_cv_have_va_copy="no"
])
])
if test "x$ac_cv_have_va_copy" = "xyes" ; then
AC_DEFINE([HAVE_VA_COPY], [1], [Define if va_copy exists])
fi
AC_CACHE_CHECK([whether __va_copy exists], ac_cv_have___va_copy, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdarg.h>
va_list x,y;
]], [[ __va_copy(x,y); ]])],
[ ac_cv_have___va_copy="yes" ], [ ac_cv_have___va_copy="no"
])
])
if test "x$ac_cv_have___va_copy" = "xyes" ; then
AC_DEFINE([HAVE___VA_COPY], [1], [Define if __va_copy exists])
fi
AC_CACHE_CHECK([whether getopt has optreset support],
ac_cv_have_getopt_optreset, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <getopt.h> ]],
[[ extern int optreset; optreset = 0; ]])],
[ ac_cv_have_getopt_optreset="yes" ],
[ ac_cv_have_getopt_optreset="no"
])
])
if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
AC_DEFINE([HAVE_GETOPT_OPTRESET], [1],
[Define if your getopt(3) defines and uses optreset])
fi
AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
[[ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);]])],
[ ac_cv_libc_defines_sys_errlist="yes" ],
[ ac_cv_libc_defines_sys_errlist="no"
])
])
if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then
AC_DEFINE([HAVE_SYS_ERRLIST], [1],
[Define if your system defines sys_errlist[]])
fi
AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
[[ extern int sys_nerr; printf("%i", sys_nerr);]])],
[ ac_cv_libc_defines_sys_nerr="yes" ],
[ ac_cv_libc_defines_sys_nerr="no"
])
])
if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then
AC_DEFINE([HAVE_SYS_NERR], [1], [Define if your system defines sys_nerr])
fi
# Check libraries needed by DNS fingerprint support
AC_SEARCH_LIBS([getrrsetbyname], [resolv],
[AC_DEFINE([HAVE_GETRRSETBYNAME], [1],
[Define if getrrsetbyname() exists])],
[
# Needed by our getrrsetbyname()
AC_SEARCH_LIBS([res_query], [resolv])
AC_SEARCH_LIBS([dn_expand], [resolv])
AC_MSG_CHECKING([if res_query will link])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
]], [[
res_query (0, 0, 0, 0, 0);
]])],
AC_MSG_RESULT([yes]),
[AC_MSG_RESULT([no])
saved_LIBS="$LIBS"
LIBS="$LIBS -lresolv"
AC_MSG_CHECKING([for res_query in -lresolv])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include <resolv.h>
]], [[
res_query (0, 0, 0, 0, 0);
]])],
[AC_MSG_RESULT([yes])],
[LIBS="$saved_LIBS"
AC_MSG_RESULT([no])])
])
AC_CHECK_FUNCS([_getshort _getlong])
AC_CHECK_DECLS([_getshort, _getlong], , ,
[#include <sys/types.h>
#include <arpa/nameser.h>])
AC_CHECK_MEMBER([HEADER.ad],
[AC_DEFINE([HAVE_HEADER_AD], [1],
[Define if HEADER.ad exists in arpa/nameser.h])], ,
[#include <arpa/nameser.h>])
])
AC_MSG_CHECKING([if struct __res_state _res is an extern])
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
extern struct __res_state _res;
]], [[
struct __res_state *volatile p = &_res; /* force resolution of _res */
return 0;
]],)],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE__RES_EXTERN], [1],
[Define if you have struct __res_state _res as an extern])
],
[ AC_MSG_RESULT([no]) ]
)
# Check whether user wants SELinux support
SELINUX_MSG="no"
LIBSELINUX=""
AC_ARG_WITH([selinux],
[ --with-selinux Enable SELinux support],
[ if test "x$withval" != "xno" ; then
save_LIBS="$LIBS"
AC_DEFINE([WITH_SELINUX], [1],
[Define if you want SELinux support.])
SELINUX_MSG="yes"
AC_CHECK_HEADER([selinux/selinux.h], ,
AC_MSG_ERROR([SELinux support requires selinux.h header]))
AC_CHECK_LIB([selinux], [setexeccon],
[ LIBSELINUX="-lselinux"
LIBS="$LIBS -lselinux"
],
AC_MSG_ERROR([SELinux support requires libselinux library]))
SSHLIBS="$SSHLIBS $LIBSELINUX"
SSHDLIBS="$SSHDLIBS $LIBSELINUX"
AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level])
LIBS="$save_LIBS"
fi ]
)
AC_SUBST([SSHLIBS])
AC_SUBST([SSHDLIBS])
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
AC_ARG_WITH([kerberos5],
[ --with-kerberos5=PATH Enable Kerberos 5 support],
[ if test "x$withval" != "xno" ; then
if test "x$withval" = "xyes" ; then
KRB5ROOT="/usr/local"
else
KRB5ROOT=${withval}
fi
AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support])
KRB5_MSG="yes"
AC_PATH_TOOL([KRB5CONF], [krb5-config],
[$KRB5ROOT/bin/krb5-config],
[$KRB5ROOT/bin:$PATH])
if test -x $KRB5CONF ; then
K5CFLAGS="`$KRB5CONF --cflags`"
K5LIBS="`$KRB5CONF --libs`"
CPPFLAGS="$CPPFLAGS $K5CFLAGS"
AC_MSG_CHECKING([for gssapi support])
if $KRB5CONF | grep gssapi >/dev/null ; then
AC_MSG_RESULT([yes])
AC_DEFINE([GSSAPI], [1],
[Define this if you want GSSAPI
support in the version 2 protocol])
GSSCFLAGS="`$KRB5CONF --cflags gssapi`"
GSSLIBS="`$KRB5CONF --libs gssapi`"
CPPFLAGS="$CPPFLAGS $GSSCFLAGS"
else
AC_MSG_RESULT([no])
fi
AC_MSG_CHECKING([whether we are using Heimdal])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
]], [[ char *tmp = heimdal_version; ]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([HEIMDAL], [1],
[Define this if you are using the Heimdal
version of Kerberos V5]) ],
[AC_MSG_RESULT([no])
])
else
CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
AC_MSG_CHECKING([whether we are using Heimdal])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
]], [[ char *tmp = heimdal_version; ]])],
[ AC_MSG_RESULT([yes])
AC_DEFINE([HEIMDAL])
K5LIBS="-lkrb5"
K5LIBS="$K5LIBS -lcom_err -lasn1"
AC_CHECK_LIB([roken], [net_write],
[K5LIBS="$K5LIBS -lroken"])
AC_CHECK_LIB([des], [des_cbc_encrypt],
[K5LIBS="$K5LIBS -ldes"])
], [ AC_MSG_RESULT([no])
K5LIBS="-lkrb5 -lk5crypto -lcom_err"
])
AC_SEARCH_LIBS([dn_expand], [resolv])
AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context],
[ AC_DEFINE([GSSAPI])
GSSLIBS="-lgssapi_krb5" ],
[ AC_CHECK_LIB([gssapi], [gss_init_sec_context],
[ AC_DEFINE([GSSAPI])
GSSLIBS="-lgssapi" ],
[ AC_CHECK_LIB([gss], [gss_init_sec_context],
[ AC_DEFINE([GSSAPI])
GSSLIBS="-lgss" ],
AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]))
])
])
AC_CHECK_HEADER([gssapi.h], ,
[ unset ac_cv_header_gssapi_h
CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
AC_CHECK_HEADERS([gssapi.h], ,
AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail])
)
]
)
oldCPP="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
AC_CHECK_HEADER([gssapi_krb5.h], ,
[ CPPFLAGS="$oldCPP" ])
fi
- if test ! -z "$need_dash_r" ; then
- LDFLAGS="$LDFLAGS -R${KRB5ROOT}/lib"
+ if test -n "${rpath_opt}" ; then
+ LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib"
fi
if test ! -z "$blibpath" ; then
blibpath="$blibpath:${KRB5ROOT}/lib"
fi
AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h])
AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h])
AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1],
[Define this if you want to use libkafs' AFS support])])
AC_CHECK_DECLS([GSS_C_NT_HOSTBASED_SERVICE], [], [], [[
#ifdef HAVE_GSSAPI_H
# include <gssapi.h>
#elif defined(HAVE_GSSAPI_GSSAPI_H)
# include <gssapi/gssapi.h>
#endif
#ifdef HAVE_GSSAPI_GENERIC_H
# include <gssapi_generic.h>
#elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H)
# include <gssapi/gssapi_generic.h>
#endif
]])
saved_LIBS="$LIBS"
LIBS="$LIBS $K5LIBS"
AC_CHECK_FUNCS([krb5_cc_new_unique krb5_get_error_message krb5_free_error_message])
LIBS="$saved_LIBS"
fi
]
)
AC_SUBST([GSSLIBS])
AC_SUBST([K5LIBS])
# Looking for programs, paths and files
PRIVSEP_PATH=/var/empty
AC_ARG_WITH([privsep-path],
[ --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
PRIVSEP_PATH=$withval
fi
]
)
AC_SUBST([PRIVSEP_PATH])
AC_ARG_WITH([xauth],
[ --with-xauth=PATH Specify path to xauth program ],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
xauth_path=$withval
fi
],
[
TestPath="$PATH"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin"
TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin"
AC_PATH_PROG([xauth_path], [xauth], , [$TestPath])
if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then
xauth_path="/usr/openwin/bin/xauth"
fi
]
)
STRIP_OPT=-s
AC_ARG_ENABLE([strip],
[ --disable-strip Disable calling strip(1) on install],
[
if test "x$enableval" = "xno" ; then
STRIP_OPT=
fi
]
)
AC_SUBST([STRIP_OPT])
if test -z "$xauth_path" ; then
XAUTH_PATH="undefined"
AC_SUBST([XAUTH_PATH])
else
AC_DEFINE_UNQUOTED([XAUTH_PATH], ["$xauth_path"],
[Define if xauth is found in your path])
XAUTH_PATH=$xauth_path
AC_SUBST([XAUTH_PATH])
fi
dnl # --with-maildir=/path/to/mail gets top priority.
dnl # if maildir is set in the platform case statement above we use that.
dnl # Otherwise we run a program to get the dir from system headers.
dnl # We first look for _PATH_MAILDIR then MAILDIR then _PATH_MAIL
dnl # If we find _PATH_MAILDIR we do nothing because that is what
dnl # session.c expects anyway. Otherwise we set to the value found
dnl # stripping any trailing slash. If for some strage reason our program
dnl # does not find what it needs, we default to /var/spool/mail.
# Check for mail directory
AC_ARG_WITH([maildir],
[ --with-maildir=/path/to/mail Specify your system mail directory],
[
if test "X$withval" != X && test "x$withval" != xno && \
test "x${withval}" != xyes; then
AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$withval"],
[Set this to your mail directory if you do not have _PATH_MAILDIR])
fi
],[
if test "X$maildir" != "X"; then
AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"])
else
AC_MSG_CHECKING([Discovering system mail directory])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
#include <string.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef HAVE_MAILLOCK_H
#include <maillock.h>
#endif
#define DATA "conftest.maildir"
]], [[
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
#if defined (_PATH_MAILDIR)
if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0)
exit(1);
#elif defined (MAILDIR)
if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0)
exit(1);
#elif defined (_PATH_MAIL)
if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0)
exit(1);
#else
exit (2);
#endif
exit(0);
]])],
[
maildir_what=`awk -F: '{print $1}' conftest.maildir`
maildir=`awk -F: '{print $2}' conftest.maildir \
| sed 's|/$||'`
AC_MSG_RESULT([Using: $maildir from $maildir_what])
if test "x$maildir_what" != "x_PATH_MAILDIR"; then
AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"])
fi
],
[
if test "X$ac_status" = "X2";then
# our test program didn't find it. Default to /var/spool/mail
AC_MSG_RESULT([Using: default value of /var/spool/mail])
AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["/var/spool/mail"])
else
AC_MSG_RESULT([*** not found ***])
fi
],
[
AC_MSG_WARN([cross compiling: use --with-maildir=/path/to/mail])
]
)
fi
]
) # maildir
if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then
AC_MSG_WARN([cross compiling: Disabling /dev/ptmx test])
disable_ptmx_check=yes
fi
if test -z "$no_dev_ptmx" ; then
if test "x$disable_ptmx_check" != "xyes" ; then
AC_CHECK_FILE(["/dev/ptmx"],
[
AC_DEFINE_UNQUOTED([HAVE_DEV_PTMX], [1],
[Define if you have /dev/ptmx])
have_dev_ptmx=1
]
)
fi
fi
if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then
AC_CHECK_FILE(["/dev/ptc"],
[
AC_DEFINE_UNQUOTED([HAVE_DEV_PTS_AND_PTC], [1],
[Define if you have /dev/ptc])
have_dev_ptc=1
]
)
else
AC_MSG_WARN([cross compiling: Disabling /dev/ptc test])
fi
# Options from here on. Some of these are preset by platform above
AC_ARG_WITH([mantype],
[ --with-mantype=man|cat|doc Set man page type],
[
case "$withval" in
man|cat|doc)
MANTYPE=$withval
;;
*)
AC_MSG_ERROR([invalid man type: $withval])
;;
esac
]
)
if test -z "$MANTYPE"; then
TestPath="/usr/bin${PATH_SEPARATOR}/usr/ucb"
AC_PATH_PROGS([NROFF], [nroff awf], [/bin/false], [$TestPath])
if ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then
MANTYPE=doc
elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then
MANTYPE=man
else
MANTYPE=cat
fi
fi
AC_SUBST([MANTYPE])
if test "$MANTYPE" = "doc"; then
mansubdir=man;
else
mansubdir=$MANTYPE;
fi
AC_SUBST([mansubdir])
# Check whether to enable MD5 passwords
MD5_MSG="no"
AC_ARG_WITH([md5-passwords],
[ --with-md5-passwords Enable use of MD5 passwords],
[
if test "x$withval" != "xno" ; then
AC_DEFINE([HAVE_MD5_PASSWORDS], [1],
[Define if you want to allow MD5 passwords])
MD5_MSG="yes"
fi
]
)
# Whether to disable shadow password support
AC_ARG_WITH([shadow],
[ --without-shadow Disable shadow password support],
[
if test "x$withval" = "xno" ; then
AC_DEFINE([DISABLE_SHADOW])
disable_shadow=yes
fi
]
)
if test -z "$disable_shadow" ; then
AC_MSG_CHECKING([if the systems has expire shadow information])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <shadow.h>
struct spwd sp;
]], [[ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ]])],
[ sp_expire_available=yes ], [
])
if test "x$sp_expire_available" = "xyes" ; then
AC_MSG_RESULT([yes])
AC_DEFINE([HAS_SHADOW_EXPIRE], [1],
[Define if you want to use shadow password expire field])
else
AC_MSG_RESULT([no])
fi
fi
# Use ip address instead of hostname in $DISPLAY
if test ! -z "$IPADDR_IN_DISPLAY" ; then
DISPLAY_HACK_MSG="yes"
AC_DEFINE([IPADDR_IN_DISPLAY], [1],
[Define if you need to use IP address
instead of hostname in $DISPLAY])
else
DISPLAY_HACK_MSG="no"
AC_ARG_WITH([ipaddr-display],
[ --with-ipaddr-display Use ip address instead of hostname in $DISPLAY],
[
if test "x$withval" != "xno" ; then
AC_DEFINE([IPADDR_IN_DISPLAY])
DISPLAY_HACK_MSG="yes"
fi
]
)
fi
# check for /etc/default/login and use it if present.
AC_ARG_ENABLE([etc-default-login],
[ --disable-etc-default-login Disable using PATH from /etc/default/login [no]],
[ if test "x$enableval" = "xno"; then
AC_MSG_NOTICE([/etc/default/login handling disabled])
etc_default_login=no
else
etc_default_login=yes
fi ],
[ if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes";
then
AC_MSG_WARN([cross compiling: not checking /etc/default/login])
etc_default_login=no
else
etc_default_login=yes
fi ]
)
if test "x$etc_default_login" != "xno"; then
AC_CHECK_FILE(["/etc/default/login"],
[ external_path_file=/etc/default/login ])
if test "x$external_path_file" = "x/etc/default/login"; then
AC_DEFINE([HAVE_ETC_DEFAULT_LOGIN], [1],
[Define if your system has /etc/default/login])
fi
fi
dnl BSD systems use /etc/login.conf so --with-default-path= has no effect
if test $ac_cv_func_login_getcapbool = "yes" && \
test $ac_cv_header_login_cap_h = "yes" ; then
external_path_file=/etc/login.conf
fi
# Whether to mess with the default path
SERVER_PATH_MSG="(default)"
AC_ARG_WITH([default-path],
[ --with-default-path= Specify default $PATH environment for server],
[
if test "x$external_path_file" = "x/etc/login.conf" ; then
AC_MSG_WARN([
--with-default-path=PATH has no effect on this system.
Edit /etc/login.conf instead.])
elif test "x$withval" != "xno" ; then
if test ! -z "$external_path_file" ; then
AC_MSG_WARN([
--with-default-path=PATH will only be used if PATH is not defined in
$external_path_file .])
fi
user_path="$withval"
SERVER_PATH_MSG="$withval"
fi
],
[ if test "x$external_path_file" = "x/etc/login.conf" ; then
AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf])
else
if test ! -z "$external_path_file" ; then
AC_MSG_WARN([
If PATH is defined in $external_path_file, ensure the path to scp is included,
otherwise scp will not work.])
fi
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
/* find out what STDPATH is */
#include <stdio.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#ifndef _PATH_STDPATH
# ifdef _PATH_USERPATH /* Irix */
# define _PATH_STDPATH _PATH_USERPATH
# else
# define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
# endif
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define DATA "conftest.stdpath"
]], [[
FILE *fd;
int rc;
fd = fopen(DATA,"w");
if(fd == NULL)
exit(1);
if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0)
exit(1);
exit(0);
]])],
[ user_path=`cat conftest.stdpath` ],
[ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ],
[ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ]
)
# make sure $bindir is in USER_PATH so scp will work
t_bindir="${bindir}"
while echo "${t_bindir}" | egrep '\$\{|NONE/' >/dev/null 2>&1; do
t_bindir=`eval echo ${t_bindir}`
case $t_bindir in
NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;;
esac
case $t_bindir in
NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;;
esac
done
echo $user_path | grep ":$t_bindir" > /dev/null 2>&1
if test $? -ne 0 ; then
echo $user_path | grep "^$t_bindir" > /dev/null 2>&1
if test $? -ne 0 ; then
user_path=$user_path:$t_bindir
AC_MSG_RESULT([Adding $t_bindir to USER_PATH so scp will work])
fi
fi
fi ]
)
if test "x$external_path_file" != "x/etc/login.conf" ; then
AC_DEFINE_UNQUOTED([USER_PATH], ["$user_path"], [Specify default $PATH])
AC_SUBST([user_path])
fi
# Set superuser path separately to user path
AC_ARG_WITH([superuser-path],
[ --with-superuser-path= Specify different path for super-user],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
AC_DEFINE_UNQUOTED([SUPERUSER_PATH], ["$withval"],
[Define if you want a different $PATH
for the superuser])
superuser_path=$withval
fi
]
)
AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses])
IPV4_IN6_HACK_MSG="no"
AC_ARG_WITH(4in6,
[ --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses],
[
if test "x$withval" != "xno" ; then
AC_MSG_RESULT([yes])
AC_DEFINE([IPV4_IN_IPV6], [1],
[Detect IPv4 in IPv6 mapped addresses
and treat as IPv4])
IPV4_IN6_HACK_MSG="yes"
else
AC_MSG_RESULT([no])
fi
], [
if test "x$inet6_default_4in6" = "xyes"; then
AC_MSG_RESULT([yes (default)])
AC_DEFINE([IPV4_IN_IPV6])
IPV4_IN6_HACK_MSG="yes"
else
AC_MSG_RESULT([no (default)])
fi
]
)
# Whether to enable BSD auth support
BSD_AUTH_MSG=no
AC_ARG_WITH([bsd-auth],
[ --with-bsd-auth Enable BSD auth support],
[
if test "x$withval" != "xno" ; then
AC_DEFINE([BSD_AUTH], [1],
[Define if you have BSD auth support])
BSD_AUTH_MSG=yes
fi
]
)
# Where to place sshd.pid
piddir=/var/run
# make sure the directory exists
if test ! -d $piddir ; then
piddir=`eval echo ${sysconfdir}`
case $piddir in
NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;;
esac
fi
AC_ARG_WITH([pid-dir],
[ --with-pid-dir=PATH Specify location of sshd.pid file],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
piddir=$withval
if test ! -d $piddir ; then
AC_MSG_WARN([** no $piddir directory on this system **])
fi
fi
]
)
AC_DEFINE_UNQUOTED([_PATH_SSH_PIDDIR], ["$piddir"],
[Specify location of ssh.pid])
AC_SUBST([piddir])
dnl allow user to disable some login recording features
AC_ARG_ENABLE([lastlog],
[ --disable-lastlog disable use of lastlog even if detected [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_LASTLOG])
fi
]
)
AC_ARG_ENABLE([utmp],
[ --disable-utmp disable use of utmp even if detected [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_UTMP])
fi
]
)
AC_ARG_ENABLE([utmpx],
[ --disable-utmpx disable use of utmpx even if detected [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_UTMPX], [1],
[Define if you don't want to use utmpx])
fi
]
)
AC_ARG_ENABLE([wtmp],
[ --disable-wtmp disable use of wtmp even if detected [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_WTMP])
fi
]
)
AC_ARG_ENABLE([wtmpx],
[ --disable-wtmpx disable use of wtmpx even if detected [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_WTMPX], [1],
[Define if you don't want to use wtmpx])
fi
]
)
AC_ARG_ENABLE([libutil],
[ --disable-libutil disable use of libutil (login() etc.) [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_LOGIN])
fi
]
)
AC_ARG_ENABLE([pututline],
[ --disable-pututline disable use of pututline() etc. ([uw]tmp) [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_PUTUTLINE], [1],
[Define if you don't want to use pututline()
etc. to write [uw]tmp])
fi
]
)
AC_ARG_ENABLE([pututxline],
[ --disable-pututxline disable use of pututxline() etc. ([uw]tmpx) [no]],
[
if test "x$enableval" = "xno" ; then
AC_DEFINE([DISABLE_PUTUTXLINE], [1],
[Define if you don't want to use pututxline()
etc. to write [uw]tmpx])
fi
]
)
AC_ARG_WITH([lastlog],
[ --with-lastlog=FILE|DIR specify lastlog location [common locations]],
[
if test "x$withval" = "xno" ; then
AC_DEFINE([DISABLE_LASTLOG])
elif test -n "$withval" && test "x${withval}" != "xyes"; then
conf_lastlog_location=$withval
fi
]
)
dnl lastlog, [uw]tmpx? detection
dnl NOTE: set the paths in the platform section to avoid the
dnl need for command-line parameters
dnl lastlog and [uw]tmp are subject to a file search if all else fails
dnl lastlog detection
dnl NOTE: the code itself will detect if lastlog is a directory
AC_MSG_CHECKING([if your system defines LASTLOG_FILE])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_LASTLOG_H
# include <lastlog.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#ifdef HAVE_LOGIN_H
# include <login.h>
#endif
]], [[ char *lastlog = LASTLOG_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[
AC_MSG_RESULT([no])
AC_MSG_CHECKING([if your system defines _PATH_LASTLOG])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_LASTLOG_H
# include <lastlog.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
]], [[ char *lastlog = _PATH_LASTLOG; ]])],
[ AC_MSG_RESULT([yes]) ],
[
AC_MSG_RESULT([no])
system_lastlog_path=no
])
])
if test -z "$conf_lastlog_location"; then
if test x"$system_lastlog_path" = x"no" ; then
for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do
if (test -d "$f" || test -f "$f") ; then
conf_lastlog_location=$f
fi
done
if test -z "$conf_lastlog_location"; then
AC_MSG_WARN([** Cannot find lastlog **])
dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx
fi
fi
fi
if test -n "$conf_lastlog_location"; then
AC_DEFINE_UNQUOTED([CONF_LASTLOG_FILE], ["$conf_lastlog_location"],
[Define if you want to specify the path to your lastlog file])
fi
dnl utmp detection
AC_MSG_CHECKING([if your system defines UTMP_FILE])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
]], [[ char *utmp = UTMP_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
system_utmp_path=no
])
if test -z "$conf_utmp_location"; then
if test x"$system_utmp_path" = x"no" ; then
for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do
if test -f $f ; then
conf_utmp_location=$f
fi
done
if test -z "$conf_utmp_location"; then
AC_DEFINE([DISABLE_UTMP])
fi
fi
fi
if test -n "$conf_utmp_location"; then
AC_DEFINE_UNQUOTED([CONF_UTMP_FILE], ["$conf_utmp_location"],
[Define if you want to specify the path to your utmp file])
fi
dnl wtmp detection
AC_MSG_CHECKING([if your system defines WTMP_FILE])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
]], [[ char *wtmp = WTMP_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
system_wtmp_path=no
])
if test -z "$conf_wtmp_location"; then
if test x"$system_wtmp_path" = x"no" ; then
for f in /usr/adm/wtmp /var/log/wtmp; do
if test -f $f ; then
conf_wtmp_location=$f
fi
done
if test -z "$conf_wtmp_location"; then
AC_DEFINE([DISABLE_WTMP])
fi
fi
fi
if test -n "$conf_wtmp_location"; then
AC_DEFINE_UNQUOTED([CONF_WTMP_FILE], ["$conf_wtmp_location"],
[Define if you want to specify the path to your wtmp file])
fi
dnl wtmpx detection
AC_MSG_CHECKING([if your system defines WTMPX_FILE])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <utmp.h>
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
]], [[ char *wtmpx = WTMPX_FILE; ]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
system_wtmpx_path=no
])
if test -z "$conf_wtmpx_location"; then
if test x"$system_wtmpx_path" = x"no" ; then
AC_DEFINE([DISABLE_WTMPX])
fi
else
AC_DEFINE_UNQUOTED([CONF_WTMPX_FILE], ["$conf_wtmpx_location"],
[Define if you want to specify the path to your wtmpx file])
fi
if test ! -z "$blibpath" ; then
LDFLAGS="$LDFLAGS $blibflags$blibpath"
AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile])
fi
AC_CHECK_MEMBER([struct lastlog.ll_line], [], [
if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then
AC_DEFINE([DISABLE_LASTLOG])
fi
], [
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UTMP_H
#include <utmp.h>
#endif
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
#ifdef HAVE_LASTLOG_H
#include <lastlog.h>
#endif
])
AC_CHECK_MEMBER([struct utmp.ut_line], [], [
AC_DEFINE([DISABLE_UTMP])
AC_DEFINE([DISABLE_WTMP])
], [
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_UTMP_H
#include <utmp.h>
#endif
#ifdef HAVE_UTMPX_H
#include <utmpx.h>
#endif
#ifdef HAVE_LASTLOG_H
#include <lastlog.h>
#endif
])
dnl Adding -Werror to CFLAGS early prevents configure tests from running.
dnl Add now.
CFLAGS="$CFLAGS $werror_flags"
if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then
TEST_SSH_IPV6=no
else
TEST_SSH_IPV6=yes
fi
AC_CHECK_DECL([BROKEN_GETADDRINFO], [TEST_SSH_IPV6=no])
AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6])
AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8])
AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS])
AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms])
AC_SUBST([DEPEND], [$(cat $srcdir/.depend)])
CFLAGS="${CFLAGS} ${CFLAGS_AFTER}"
LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}"
AC_EXEEXT
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
openbsd-compat/Makefile openbsd-compat/regress/Makefile \
survey.sh])
AC_OUTPUT
# Print summary of options
# Someone please show me a better way :)
A=`eval echo ${prefix}` ; A=`eval echo ${A}`
B=`eval echo ${bindir}` ; B=`eval echo ${B}`
C=`eval echo ${sbindir}` ; C=`eval echo ${C}`
D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}`
E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}`
F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}`
G=`eval echo ${piddir}` ; G=`eval echo ${G}`
H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}`
I=`eval echo ${user_path}` ; I=`eval echo ${I}`
J=`eval echo ${superuser_path}` ; J=`eval echo ${J}`
echo ""
echo "OpenSSH has been configured with the following options:"
echo " User binaries: $B"
echo " System binaries: $C"
echo " Configuration files: $D"
echo " Askpass program: $E"
echo " Manual pages: $F"
echo " PID file: $G"
echo " Privilege separation chroot path: $H"
if test "x$external_path_file" = "x/etc/login.conf" ; then
echo " At runtime, sshd will use the path defined in $external_path_file"
echo " Make sure the path to scp is present, otherwise scp will not work"
else
echo " sshd default user PATH: $I"
if test ! -z "$external_path_file"; then
echo " (If PATH is set in $external_path_file it will be used instead. If"
echo " used, ensure the path to scp is present, otherwise scp will not work.)"
fi
fi
if test ! -z "$superuser_path" ; then
echo " sshd superuser user PATH: $J"
fi
echo " Manpage format: $MANTYPE"
echo " PAM support: $PAM_MSG"
echo " OSF SIA support: $SIA_MSG"
echo " KerberosV support: $KRB5_MSG"
echo " SELinux support: $SELINUX_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " libldns support: $LDNS_MSG"
echo " Solaris process contract support: $SPC_MSG"
echo " Solaris project support: $SP_MSG"
echo " Solaris privilege support: $SPP_MSG"
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
echo ""
echo " Host: ${host}"
echo " Compiler: ${CC}"
echo " Compiler flags: ${CFLAGS}"
echo "Preprocessor flags: ${CPPFLAGS}"
echo " Linker flags: ${LDFLAGS}"
echo " Libraries: ${LIBS}"
if test ! -z "${SSHDLIBS}"; then
echo " +for sshd: ${SSHDLIBS}"
fi
if test ! -z "${SSHLIBS}"; then
echo " +for ssh: ${SSHLIBS}"
fi
echo ""
if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then
echo "SVR4 style packages are supported with \"make package\""
echo ""
fi
if test "x$PAM_MSG" = "xyes" ; then
echo "PAM is enabled. You may need to install a PAM control file "
echo "for sshd, otherwise password authentication may fail. "
echo "Example PAM control files can be found in the contrib/ "
echo "subdirectory"
echo ""
fi
if test ! -z "$NO_PEERCHECK" ; then
echo "WARNING: the operating system that you are using does not"
echo "appear to support getpeereid(), getpeerucred() or the"
echo "SO_PEERCRED getsockopt() option. These facilities are used to"
echo "enforce security checks to prevent unauthorised connections to"
echo "ssh-agent. Their absence increases the risk that a malicious"
echo "user can connect to your agent."
echo ""
fi
if test "$AUDIT_MODULE" = "bsm" ; then
echo "WARNING: BSM audit support is currently considered EXPERIMENTAL."
echo "See the Solaris section in README.platform for details."
fi
diff --git a/contrib/cygwin/ssh-host-config b/contrib/cygwin/ssh-host-config
index 261020af33e8..a8572e2ac879 100644
--- a/contrib/cygwin/ssh-host-config
+++ b/contrib/cygwin/ssh-host-config
@@ -1,693 +1,714 @@
#!/bin/bash
#
# ssh-host-config, Copyright 2000-2014 Red Hat Inc.
#
# This file is part of the Cygwin port of OpenSSH.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
# THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ======================================================================
# Initialization
# ======================================================================
CSIH_SCRIPT=/usr/share/csih/cygwin-service-installation-helper.sh
# List of apps used. This is checkad for existence in csih_sanity_check
# Don't use *any* transient commands before sourcing the csih helper script,
# otherwise the sanity checks are short-circuited.
declare -a csih_required_commands=(
/usr/bin/basename coreutils
/usr/bin/cat coreutils
/usr/bin/chmod coreutils
/usr/bin/dirname coreutils
/usr/bin/id coreutils
/usr/bin/mv coreutils
/usr/bin/rm coreutils
/usr/bin/cygpath cygwin
/usr/bin/mkpasswd cygwin
/usr/bin/mount cygwin
/usr/bin/ps cygwin
/usr/bin/umount cygwin
/usr/bin/cmp diffutils
/usr/bin/grep grep
/usr/bin/awk gawk
/usr/bin/ssh-keygen openssh
/usr/sbin/sshd openssh
/usr/bin/sed sed
)
csih_sanity_check_server=yes
source ${CSIH_SCRIPT}
PROGNAME=$(/usr/bin/basename $0)
_tdir=$(/usr/bin/dirname $0)
PROGDIR=$(cd $_tdir && pwd)
# Subdirectory where the new package is being installed
PREFIX=/usr
# Directory where the config files are stored
SYSCONFDIR=/etc
LOCALSTATEDIR=/var
sshd_config_configured=no
port_number=22
-service_name=sshd
+service_name=cygsshd
strictmodes=yes
cygwin_value=""
user_account=
password_value=
opt_force=no
# ======================================================================
# Routine: update_services_file
# ======================================================================
update_services_file() {
local _my_etcdir="/ssh-host-config.$$"
local _win_etcdir
local _services
local _spaces
local _serv_tmp
local _wservices
local ret=0
_win_etcdir="${SYSTEMROOT}\\system32\\drivers\\etc"
_services="${_my_etcdir}/services"
_spaces=" #"
_serv_tmp="${_my_etcdir}/srv.out.$$"
/usr/bin/mount -o text,posix=0,noacl -f "${_win_etcdir}" "${_my_etcdir}"
# Depends on the above mount
_wservices=`cygpath -w "${_services}"`
# Add ssh 22/tcp and ssh 22/udp to services
if [ `/usr/bin/grep -q 'ssh[[:space:]][[:space:]]*22' "${_services}"; echo $?` -ne 0 ]
then
if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}"
then
if /usr/bin/mv "${_serv_tmp}" "${_services}"
then
csih_inform "Added ssh to ${_wservices}"
else
csih_warning "Adding ssh to ${_wservices} failed!"
let ++ret
fi
/usr/bin/rm -f "${_serv_tmp}"
else
csih_warning "Adding ssh to ${_wservices} failed!"
let ++ret
fi
fi
/usr/bin/umount "${_my_etcdir}"
return $ret
} # --- End of update_services_file --- #
# ======================================================================
# Routine: sshd_strictmodes
# MODIFIES: strictmodes
# ======================================================================
sshd_strictmodes() {
if [ "${sshd_config_configured}" != "yes" ]
then
echo
csih_inform "StrictModes is set to 'yes' by default."
csih_inform "This is the recommended setting, but it requires that the POSIX"
csih_inform "permissions of the user's home directory, the user's .ssh"
csih_inform "directory, and the user's ssh key files are tight so that"
csih_inform "only the user has write permissions."
csih_inform "On the other hand, StrictModes don't work well with default"
csih_inform "Windows permissions of a home directory mounted with the"
csih_inform "'noacl' option, and they don't work at all if the home"
csih_inform "directory is on a FAT or FAT32 partition."
if ! csih_request "Should StrictModes be used?"
then
strictmodes=no
fi
fi
return 0
}
# ======================================================================
# Routine: sshd_privsep
# Try to create ssshd user account
# ======================================================================
sshd_privsep() {
local ret=0
if [ "${sshd_config_configured}" != "yes" ]
then
if ! csih_create_unprivileged_user sshd
then
csih_error_recoverable "Could not create user 'sshd'!"
csih_error_recoverable "You will not be able to run an sshd service"
csih_error_recoverable "under a privileged account successfully."
csih_error_recoverable "Make sure to create a non-privileged user 'sshd'"
csih_error_recoverable "manually before trying to run the service!"
let ++ret
fi
fi
return $ret
} # --- End of sshd_privsep --- #
# ======================================================================
# Routine: sshd_config_tweak
# ======================================================================
sshd_config_tweak() {
local ret=0
# Modify sshd_config
csih_inform "Updating ${SYSCONFDIR}/sshd_config file"
if [ "${port_number}" -ne 22 ]
then
/usr/bin/sed -i -e "s/^#\?[[:space:]]*Port[[:space:]].*/Port ${port_number}/" \
${SYSCONFDIR}/sshd_config
if [ $? -ne 0 ]
then
csih_warning "Setting listening port to ${port_number} failed!"
csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
let ++ret
fi
fi
if [ "${strictmodes}" = "no" ]
then
/usr/bin/sed -i -e "s/^#\?[[:space:]]*StrictModes[[:space:]].*/StrictModes no/" \
${SYSCONFDIR}/sshd_config
if [ $? -ne 0 ]
then
csih_warning "Setting StrictModes to 'no' failed!"
csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
let ++ret
fi
fi
return $ret
} # --- End of sshd_config_tweak --- #
# ======================================================================
# Routine: update_inetd_conf
# ======================================================================
update_inetd_conf() {
local _inetcnf="${SYSCONFDIR}/inetd.conf"
local _inetcnf_tmp="${SYSCONFDIR}/inetd.conf.$$"
local _inetcnf_dir="${SYSCONFDIR}/inetd.d"
local _sshd_inetd_conf="${_inetcnf_dir}/sshd-inetd"
local _sshd_inetd_conf_tmp="${_inetcnf_dir}/sshd-inetd.$$"
local _with_comment=1
local ret=0
if [ -d "${_inetcnf_dir}" ]
then
# we have inetutils-1.5 inetd.d support
if [ -f "${_inetcnf}" ]
then
/usr/bin/grep -q '^[[:space:]]*ssh' "${_inetcnf}" && _with_comment=0
# check for sshd OR ssh in top-level inetd.conf file, and remove
# will be replaced by a file in inetd.d/
if [ $(/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?) -eq 0 ]
then
/usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}"
if [ -f "${_inetcnf_tmp}" ]
then
if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}"
then
csih_inform "Removed ssh[d] from ${_inetcnf}"
else
csih_warning "Removing ssh[d] from ${_inetcnf} failed!"
let ++ret
fi
/usr/bin/rm -f "${_inetcnf_tmp}"
else
csih_warning "Removing ssh[d] from ${_inetcnf} failed!"
let ++ret
fi
fi
fi
csih_install_config "${_sshd_inetd_conf}" "${SYSCONFDIR}/defaults"
if /usr/bin/cmp "${SYSCONFDIR}/defaults${_sshd_inetd_conf}" "${_sshd_inetd_conf}" >/dev/null 2>&1
then
if [ "${_with_comment}" -eq 0 ]
then
/usr/bin/sed -e 's/@COMMENT@[[:space:]]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}"
else
/usr/bin/sed -e 's/@COMMENT@[[:space:]]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}"
fi
if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}"
then
csih_inform "Updated ${_sshd_inetd_conf}"
else
csih_warning "Updating ${_sshd_inetd_conf} failed!"
let ++ret
fi
fi
elif [ -f "${_inetcnf}" ]
then
/usr/bin/grep -q '^[[:space:]]*sshd' "${_inetcnf}" && _with_comment=0
# check for sshd in top-level inetd.conf file, and remove
# will be replaced by a file in inetd.d/
if [ `/usr/bin/grep -q '^#\?[[:space:]]*sshd' "${_inetcnf}"; echo $?` -eq 0 ]
then
/usr/bin/grep -v '^#\?[[:space:]]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}"
if [ -f "${_inetcnf_tmp}" ]
then
if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}"
then
csih_inform "Removed sshd from ${_inetcnf}"
else
csih_warning "Removing sshd from ${_inetcnf} failed!"
let ++ret
fi
/usr/bin/rm -f "${_inetcnf_tmp}"
else
csih_warning "Removing sshd from ${_inetcnf} failed!"
let ++ret
fi
fi
# Add ssh line to inetd.conf
if [ `/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -ne 0 ]
then
if [ "${_with_comment}" -eq 0 ]
then
echo 'ssh stream tcp nowait root /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
else
echo '# ssh stream tcp nowait root /usr/sbin/sshd sshd -i' >> "${_inetcnf}"
fi
if [ $? -eq 0 ]
then
csih_inform "Added ssh to ${_inetcnf}"
else
csih_warning "Adding ssh to ${_inetcnf} failed!"
let ++ret
fi
fi
fi
return $ret
} # --- End of update_inetd_conf --- #
# ======================================================================
# Routine: check_service_files_ownership
# Checks that the files in /etc and /var belong to the right owner
# ======================================================================
check_service_files_ownership() {
local run_service_as=$1
local ret=0
if [ -z "${run_service_as}" ]
then
- accnt_name=$(/usr/bin/cygrunsrv -VQ sshd |
+ accnt_name=$(/usr/bin/cygrunsrv -VQ "${service_name}" |
/usr/bin/sed -ne 's/^Account *: *//gp')
if [ "${accnt_name}" = "LocalSystem" ]
then
# Convert "LocalSystem" to "SYSTEM" as is the correct account name
run_service_as="SYSTEM"
else
dom="${accnt_name%%\\*}"
accnt_name="${accnt_name#*\\}"
if [ "${dom}" = '.' ]
then
# Check local account
run_service_as=$(/usr/bin/mkpasswd -l -u "${accnt_name}" |
/usr/bin/awk -F: '{print $1;}')
else
# Check domain
run_service_as=$(/usr/bin/mkpasswd -d "${dom}" -u "${accnt_name}" |
/usr/bin/awk -F: '{print $1;}')
fi
fi
if [ -z "${run_service_as}" ]
then
- csih_warning "Couldn't determine name of user running sshd service from account database!"
+ csih_warning "Couldn't determine name of user running ${service_name} service from account database!"
csih_warning "As a result, this script cannot make sure that the files used"
- csih_warning "by the sshd service belong to the user running the service."
+ csih_warning "by the ${service_name} service belong to the user running the service."
return 1
fi
fi
for i in "${SYSCONFDIR}"/ssh_config "${SYSCONFDIR}"/sshd_config "${SYSCONFDIR}"/ssh_host_*key "${SYSCONFDIR}"/ssh_host_*key.pub
do
if [ -f "$i" ]
then
if ! chown "${run_service_as}".544 "$i" >/dev/null 2>&1
then
csih_warning "Couldn't change owner of $i!"
let ++ret
fi
fi
done
if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/empty >/dev/null 2>&1
then
csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/empty!"
let ++ret
fi
if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/log/lastlog >/dev/null 2>&1
then
csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/log/lastlog!"
let ++ret
fi
if [ -f ${LOCALSTATEDIR}/log/sshd.log ]
then
if ! chown "${run_service_as}".544 ${LOCALSTATEDIR}/log/sshd.log >/dev/null 2>&1
then
csih_warning "Couldn't change owner of ${LOCALSTATEDIR}/log/sshd.log!"
let ++ret
fi
fi
if [ $ret -ne 0 ]
then
csih_warning "Couldn't change owner of important files to ${run_service_as}!"
- csih_warning "This may cause the sshd service to fail! Please make sure that"
- csih_warning "you have suufficient permissions to change the ownership of files"
+ csih_warning "This may cause the ${service_name} service to fail! Please make sure that"
+ csih_warning "you have sufficient permissions to change the ownership of files"
csih_warning "and try to run the ssh-host-config script again."
fi
return $ret
} # --- End of check_service_files_ownership --- #
# ======================================================================
# Routine: install_service
# Install sshd as a service
# ======================================================================
install_service() {
local run_service_as
local password
local ret=0
echo
if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1
then
csih_inform "Sshd service is already installed."
check_service_files_ownership "" || let ret+=$?
else
echo -e "${_csih_QUERY_STR} Do you want to install sshd as a service?"
if csih_request "(Say \"no\" if it is already installed as a service)"
then
csih_get_cygenv "${cygwin_value}"
- if ( csih_is_nt2003 || [ "$csih_FORCE_PRIVILEGED_USER" = "yes" ] )
+ if ( [ "$csih_FORCE_PRIVILEGED_USER" != "yes" ] )
then
- csih_inform "On Windows Server 2003, Windows Vista, and above, the"
- csih_inform "SYSTEM account cannot setuid to other users -- a capability"
- csih_inform "sshd requires. You need to have or to create a privileged"
- csih_inform "account. This script will help you do so."
- echo
+ # Enforce using privileged user on 64 bit Vista or W7 under WOW64
+ is_wow64=$(/usr/bin/uname | /usr/bin/grep -q 'WOW' && echo 1 || echo 0)
+ if ( csih_is_nt2003 && ! csih_is_windows8 && [ "${is_wow64}" = "1" ] )
+ then
+ csih_inform "Running 32 bit Cygwin on 64 bit Windows Vista or Windows 7"
+ csih_inform "the SYSTEM account is not sufficient to setuid to a local"
+ csih_inform "user account. You need to have or to create a privileged"
+ csih_inform "account. This script will help you do so."
+ echo
+ csih_FORCE_PRIVILEGED_USER=yes
+ fi
+ fi
+
+ if ( [ "$csih_FORCE_PRIVILEGED_USER" = "yes" ] )
+ then
[ "${opt_force}" = "yes" ] && opt_f=-f
[ -n "${user_account}" ] && opt_u="-u ""${user_account}"""
csih_select_privileged_username ${opt_f} ${opt_u} sshd
if ! csih_create_privileged_user "${password_value}"
then
csih_error_recoverable "There was a serious problem creating a privileged user."
csih_request "Do you want to proceed anyway?" || exit 1
let ++ret
fi
+ # Never returns empty if NT or above
+ run_service_as=$(csih_service_should_run_as)
+ else
+ run_service_as="SYSTEM"
fi
- # Never returns empty if NT or above
- run_service_as=$(csih_service_should_run_as)
-
if [ "${run_service_as}" = "${csih_PRIVILEGED_USERNAME}" ]
then
password="${csih_PRIVILEGED_PASSWORD}"
if [ -z "${password}" ]
then
csih_get_value "Please enter the password for user '${run_service_as}':" "-s"
password="${csih_value}"
fi
fi
# At this point, we either have $run_service_as = "system" and
# $password is empty, or $run_service_as is some privileged user and
# (hopefully) $password contains the correct password. So, from here
# out, we use '-z "${password}"' to discriminate the two cases.
csih_check_user "${run_service_as}"
if [ -n "${csih_cygenv}" ]
then
cygwin_env=( -e "CYGWIN=${csih_cygenv}" )
fi
if [ -z "${password}" ]
then
if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \
-a "-D" -y tcpip "${cygwin_env[@]}"
then
echo
csih_inform "The sshd service has been installed under the LocalSystem"
csih_inform "account (also known as SYSTEM). To start the service now, call"
- csih_inform "\`net start sshd' or \`cygrunsrv -S sshd'. Otherwise, it"
+ csih_inform "\`net start ${service_name}' or \`cygrunsrv -S ${service_name}'. Otherwise, it"
csih_inform "will start automatically after the next reboot."
fi
else
if /usr/bin/cygrunsrv -I ${service_name} -d "CYGWIN ${service_name}" -p /usr/sbin/sshd \
-a "-D" -y tcpip "${cygwin_env[@]}" \
-u "${run_service_as}" -w "${password}"
then
/usr/bin/editrights -u "${run_service_as}" -a SeServiceLogonRight
echo
csih_inform "The sshd service has been installed under the '${run_service_as}'"
csih_inform "account. To start the service now, call \`net start ${service_name}' or"
csih_inform "\`cygrunsrv -S ${service_name}'. Otherwise, it will start automatically"
csih_inform "after the next reboot."
fi
fi
if /usr/bin/cygrunsrv -Q ${service_name} >/dev/null 2>&1
then
check_service_files_ownership "${run_service_as}" || let ret+=$?
else
csih_error_recoverable "Installing sshd as a service failed!"
let ++ret
fi
fi # user allowed us to install as service
fi # service not yet installed
return $ret
} # --- End of install_service --- #
# ======================================================================
# Main Entry Point
# ======================================================================
# Check how the script has been started. If
# (1) it has been started by giving the full path and
# that path is /etc/postinstall, OR
# (2) Otherwise, if the environment variable
# SSH_HOST_CONFIG_AUTO_ANSWER_NO is set
# then set auto_answer to "no". This allows automatic
# creation of the config files in /etc w/o overwriting
# them if they already exist. In both cases, color
# escape sequences are suppressed, so as to prevent
# cluttering setup's logfiles.
if [ "$PROGDIR" = "/etc/postinstall" ]
then
csih_auto_answer="no"
csih_disable_color
opt_force=yes
fi
if [ -n "${SSH_HOST_CONFIG_AUTO_ANSWER_NO}" ]
then
csih_auto_answer="no"
csih_disable_color
opt_force=yes
fi
# ======================================================================
# Parse options
# ======================================================================
while :
do
case $# in
0)
break
;;
esac
option=$1
shift
case "${option}" in
-d | --debug )
set -x
csih_trace_on
;;
-y | --yes )
csih_auto_answer=yes
opt_force=yes
;;
-n | --no )
csih_auto_answer=no
opt_force=yes
;;
-c | --cygwin )
cygwin_value="$1"
shift
;;
-N | --name )
service_name=$1
shift
;;
-p | --port )
port_number=$1
shift
;;
-u | --user )
user_account="$1"
shift
;;
-w | --pwd )
password_value="$1"
shift
;;
--privileged )
csih_FORCE_PRIVILEGED_USER=yes
;;
*)
echo "usage: ${progname} [OPTION]..."
echo
echo "This script creates an OpenSSH host configuration."
echo
echo "Options:"
echo " --debug -d Enable shell's debug output."
echo " --yes -y Answer all questions with \"yes\" automatically."
echo " --no -n Answer all questions with \"no\" automatically."
echo " --cygwin -c <options> Use \"options\" as value for CYGWIN environment var."
echo " --name -N <name> sshd windows service name."
echo " --port -p <n> sshd listens on port n."
echo " --user -u <account> privileged user for service, default 'cyg_server'."
echo " --pwd -w <passwd> Use \"pwd\" as password for privileged user."
echo " --privileged On Windows XP, require privileged user"
echo " instead of LocalSystem for sshd service."
echo
exit 1
;;
esac
done
# ======================================================================
# Action!
# ======================================================================
# Check for running ssh/sshd processes first. Refuse to do anything while
# some ssh processes are still running
if /usr/bin/ps -ef | /usr/bin/grep -q '/sshd\?$'
then
echo
csih_error "There are still ssh processes running. Please shut them down first."
fi
# Make sure the user is running in an administrative context
admin=$(/usr/bin/id -G | /usr/bin/grep -Eq '\<544\>' && echo yes || echo no)
if [ "${admin}" != "yes" ]
then
echo
csih_warning "Running this script typically requires administrator privileges!"
csih_warning "However, it seems your account does not have these privileges."
csih_warning "Here's the list of groups in your user token:"
echo
/usr/bin/id -Gnz | xargs -0n1 echo " "
echo
csih_warning "This usually means you're running this script from a non-admin"
csih_warning "desktop session, or in a non-elevated shell under UAC control."
echo
csih_warning "Make sure you have the appropriate privileges right now,"
csih_warning "otherwise parts of this script will probably fail!"
echo
echo -e "${_csih_QUERY_STR} Are you sure you want to continue? (Say \"no\" if you're not sure"
if ! csih_request "you have the required privileges)"
then
echo
csih_inform "Ok. Exiting. Make sure to switch to an administrative account"
csih_inform "or to start this script from an elevated shell."
exit 1
fi
fi
echo
warning_cnt=0
# Create /var/log/lastlog if not already exists
if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ]
then
echo
csih_error_multi "${LOCALSTATEDIR}/log/lastlog exists, but is not a file." \
"Cannot create ssh host configuration."
fi
if [ ! -e ${LOCALSTATEDIR}/log/lastlog ]
then
/usr/bin/cat /dev/null > ${LOCALSTATEDIR}/log/lastlog
if ! /usr/bin/chmod 644 ${LOCALSTATEDIR}/log/lastlog >/dev/null 2>&1
then
csih_warning "Can't set permissions on ${LOCALSTATEDIR}/log/lastlog!"
let ++warning_cnt
fi
fi
# Create /var/empty file used as chroot jail for privilege separation
csih_make_dir "${LOCALSTATEDIR}/empty" "Cannot create ${LOCALSTATEDIR}/empty directory."
if ! /usr/bin/chmod 755 "${LOCALSTATEDIR}/empty" >/dev/null 2>&1
then
csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!"
let ++warning_cnt
fi
# generate missing host keys
csih_inform "Generating missing SSH host keys"
/usr/bin/ssh-keygen -A || let warning_cnt+=$?
# handle ssh_config
csih_install_config "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
if /usr/bin/cmp "${SYSCONFDIR}/ssh_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/ssh_config" >/dev/null 2>&1
then
if [ "${port_number}" != "22" ]
then
csih_inform "Updating ${SYSCONFDIR}/ssh_config file with requested port"
echo "Host localhost" >> ${SYSCONFDIR}/ssh_config
echo " Port ${port_number}" >> ${SYSCONFDIR}/ssh_config
fi
fi
# handle sshd_config
+# make sure not to change the existing file
+mod_before=""
+if [ -e "${SYSCONFDIR}/sshd_config" ]
+then
+ mod_before=$(stat "${SYSCONFDIR}/sshd_config" | grep '^Modify:')
+fi
csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
+mod_now=$(stat "${SYSCONFDIR}/sshd_config" | grep '^Modify:')
if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1
then
sshd_config_configured=yes
fi
-sshd_strictmodes || let warning_cnt+=$?
-sshd_privsep || let warning_cnt+=$?
-sshd_config_tweak || let warning_cnt+=$?
+if [ "${mod_before}" != "${mod_now}" ]
+then
+ sshd_strictmodes || let warning_cnt+=$?
+ sshd_config_tweak || let warning_cnt+=$?
+fi
+#sshd_privsep || let warning_cnt+=$?
update_services_file || let warning_cnt+=$?
update_inetd_conf || let warning_cnt+=$?
install_service || let warning_cnt+=$?
echo
if [ $warning_cnt -eq 0 ]
then
csih_inform "Host configuration finished. Have fun!"
else
csih_warning "Host configuration exited with ${warning_cnt} errors or warnings!"
csih_warning "Make sure that all problems reported are fixed,"
csih_warning "then re-run ssh-host-config."
fi
exit $warning_cnt
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec
index d7823483d10d..f3c175523a63 100644
--- a/contrib/redhat/openssh.spec
+++ b/contrib/redhat/openssh.spec
@@ -1,843 +1,843 @@
-%define ver 7.9p1
+%define ver 8.0p1
%define rel 1%{?dist}
# OpenSSH privilege separation requires a user & group ID
%define sshd_uid 74
%define sshd_gid 74
# Version of ssh-askpass
%define aversion 1.2.4.1
# Do we want to disable building of x11-askpass? (1=yes 0=no)
%define no_x11_askpass 0
# Do we want to disable building of gnome-askpass? (1=yes 0=no)
%define no_gnome_askpass 0
# Do we want to link against a static libcrypto? (1=yes 0=no)
%define static_libcrypto 0
# Do we want smartcard support (1=yes 0=no)
%define scard 0
# Use GTK2 instead of GNOME in gnome-ssh-askpass
%define gtk2 1
# Use build6x options for older RHEL builds
# RHEL 7 not yet supported
%if 0%{?rhel} > 6
%define build6x 0
%else
%define build6x 1
%endif
%if 0%{?fedora} >= 26
%define compat_openssl 1
%else
%define compat_openssl 0
%endif
# Do we want kerberos5 support (1=yes 0=no)
%define kerberos5 1
# Reserve options to override askpass settings with:
# rpm -ba|--rebuild --define 'skip_xxx 1'
%{?skip_x11_askpass:%define no_x11_askpass 1}
%{?skip_gnome_askpass:%define no_gnome_askpass 1}
# Add option to build without GTK2 for older platforms with only GTK+.
# RedHat <= 7.2 and Red Hat Advanced Server 2.1 are examples.
# rpm -ba|--rebuild --define 'no_gtk2 1'
%{?no_gtk2:%define gtk2 0}
# Is this a build for RHL 6.x or earlier?
%{?build_6x:%define build6x 1}
# If this is RHL 6.x, the default configuration has sysconfdir in /usr/etc.
%if %{build6x}
%define _sysconfdir /etc
%endif
# Options for static OpenSSL link:
# rpm -ba|--rebuild --define "static_openssl 1"
%{?static_openssl:%define static_libcrypto 1}
# Options for Smartcard support: (needs libsectok and openssl-engine)
# rpm -ba|--rebuild --define "smartcard 1"
%{?smartcard:%define scard 1}
# Is this a build for the rescue CD (without PAM, with MD5)? (1=yes 0=no)
%define rescue 0
%{?build_rescue:%define rescue 1}
# Turn off some stuff for resuce builds
%if %{rescue}
%define kerberos5 0
%endif
Summary: The OpenSSH implementation of SSH protocol version 2.
Name: openssh
Version: %{ver}
%if %{rescue}
Release: %{rel}rescue
%else
Release: %{rel}
%endif
URL: https://www.openssh.com/portable.html
Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
Source1: http://www.jmknoble.net/software/x11-ssh-askpass/x11-ssh-askpass-%{aversion}.tar.gz
License: BSD
Group: Applications/Internet
BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
Obsoletes: ssh
%if %{build6x}
PreReq: initscripts >= 5.00
%else
Requires: initscripts >= 5.20
%endif
BuildRequires: perl
%if %{compat_openssl}
BuildRequires: compat-openssl10-devel
%else
BuildRequires: openssl-devel >= 1.0.1
BuildRequires: openssl-devel < 1.1
%endif
BuildRequires: /bin/login
%if ! %{build6x}
BuildRequires: glibc-devel, pam
%else
BuildRequires: /usr/include/security/pam_appl.h
%endif
%if ! %{no_x11_askpass}
BuildRequires: /usr/include/X11/Xlib.h
# Xt development tools
BuildRequires: libXt-devel
# Provides xmkmf
BuildRequires: imake
# Rely on relatively recent gtk
BuildRequires: gtk2-devel
%endif
%if ! %{no_gnome_askpass}
BuildRequires: pkgconfig
%endif
%if %{kerberos5}
BuildRequires: krb5-devel
BuildRequires: krb5-libs
%endif
%package clients
Summary: OpenSSH clients.
Requires: openssh = %{version}-%{release}
Group: Applications/Internet
Obsoletes: ssh-clients
%package server
Summary: The OpenSSH server daemon.
Group: System Environment/Daemons
Obsoletes: ssh-server
Requires: openssh = %{version}-%{release}, chkconfig >= 0.9
%if ! %{build6x}
Requires: /etc/pam.d/system-auth
%endif
%package askpass
Summary: A passphrase dialog for OpenSSH and X.
Group: Applications/Internet
Requires: openssh = %{version}-%{release}
Obsoletes: ssh-extras
%package askpass-gnome
Summary: A passphrase dialog for OpenSSH, X, and GNOME.
Group: Applications/Internet
Requires: openssh = %{version}-%{release}
Obsoletes: ssh-extras
%description
SSH (Secure SHell) is a program for logging into and executing
commands on a remote machine. SSH is intended to replace rlogin and
rsh, and to provide secure encrypted communications between two
untrusted hosts over an insecure network. X11 connections and
arbitrary TCP/IP ports can also be forwarded over the secure channel.
OpenSSH is OpenBSD's version of the last free version of SSH, bringing
it up to date in terms of security and features, as well as removing
all patented algorithms to separate libraries.
This package includes the core files necessary for both the OpenSSH
client and server. To make this package useful, you should also
install openssh-clients, openssh-server, or both.
%description clients
OpenSSH is a free version of SSH (Secure SHell), a program for logging
into and executing commands on a remote machine. This package includes
the clients necessary to make encrypted connections to SSH servers.
You'll also need to install the openssh package on OpenSSH clients.
%description server
OpenSSH is a free version of SSH (Secure SHell), a program for logging
into and executing commands on a remote machine. This package contains
the secure shell daemon (sshd). The sshd daemon allows SSH clients to
securely connect to your SSH server. You also need to have the openssh
package installed.
%description askpass
OpenSSH is a free version of SSH (Secure SHell), a program for logging
into and executing commands on a remote machine. This package contains
an X11 passphrase dialog for OpenSSH.
%description askpass-gnome
OpenSSH is a free version of SSH (Secure SHell), a program for logging
into and executing commands on a remote machine. This package contains
an X11 passphrase dialog for OpenSSH and the GNOME GUI desktop
environment.
%prep
%if ! %{no_x11_askpass}
%setup -q -a 1
%else
%setup -q
%endif
%build
%if %{rescue}
CFLAGS="$RPM_OPT_FLAGS -Os"; export CFLAGS
%endif
%configure \
--sysconfdir=%{_sysconfdir}/ssh \
--libexecdir=%{_libexecdir}/openssh \
--datadir=%{_datadir}/openssh \
--with-default-path=/usr/local/bin:/bin:/usr/bin \
--with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \
--with-privsep-path=%{_var}/empty/sshd \
--with-md5-passwords \
--mandir=%{_mandir} \
--with-mantype=man \
--disable-strip \
%if %{scard}
--with-smartcard \
%endif
%if %{rescue}
--without-pam \
%else
--with-pam \
%endif
%if %{kerberos5}
--with-kerberos5=$K5DIR \
%endif
%if %{static_libcrypto}
perl -pi -e "s|-lcrypto|%{_libdir}/libcrypto.a|g" Makefile
%endif
make
%if ! %{no_x11_askpass}
pushd x11-ssh-askpass-%{aversion}
%configure --libexecdir=%{_libexecdir}/openssh
xmkmf -a
make
popd
%endif
# Define a variable to toggle gnome1/gtk2 building. This is necessary
# because RPM doesn't handle nested %if statements.
%if %{gtk2}
gtk2=yes
%else
gtk2=no
%endif
%if ! %{no_gnome_askpass}
pushd contrib
if [ $gtk2 = yes ] ; then
make gnome-ssh-askpass2
mv gnome-ssh-askpass2 gnome-ssh-askpass
else
make gnome-ssh-askpass1
mv gnome-ssh-askpass1 gnome-ssh-askpass
fi
popd
%endif
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh
mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh
mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd
make install DESTDIR=$RPM_BUILD_ROOT
install -d $RPM_BUILD_ROOT/etc/pam.d/
install -d $RPM_BUILD_ROOT/etc/rc.d/init.d
install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh
%if %{build6x}
install -m644 contrib/redhat/sshd.pam.old $RPM_BUILD_ROOT/etc/pam.d/sshd
%else
install -m644 contrib/redhat/sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd
%endif
install -m755 contrib/redhat/sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd
%if ! %{no_x11_askpass}
install x11-ssh-askpass-%{aversion}/x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/x11-ssh-askpass
ln -s x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass
%endif
%if ! %{no_gnome_askpass}
install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass
%endif
%if ! %{scard}
rm -f $RPM_BUILD_ROOT/usr/share/openssh/Ssh.bin
%endif
%if ! %{no_gnome_askpass}
install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/
install -m 755 contrib/redhat/gnome-ssh-askpass.csh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/
install -m 755 contrib/redhat/gnome-ssh-askpass.sh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/
%endif
perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/*
%clean
rm -rf $RPM_BUILD_ROOT
%triggerun server -- ssh-server
if [ "$1" != 0 -a -r /var/run/sshd.pid ] ; then
touch /var/run/sshd.restart
fi
%triggerun server -- openssh-server < 2.5.0p1
# Count the number of HostKey and HostDsaKey statements we have.
gawk 'BEGIN {IGNORECASE=1}
/^hostkey/ || /^hostdsakey/ {sawhostkey = sawhostkey + 1}
END {exit sawhostkey}' /etc/ssh/sshd_config
# And if we only found one, we know the client was relying on the old default
# behavior, which loaded the the SSH2 DSA host key when HostDsaKey wasn't
# specified. Now that HostKey is used for both SSH1 and SSH2 keys, specifying
# one nullifies the default, which would have loaded both.
if [ $? -eq 1 ] ; then
echo HostKey /etc/ssh/ssh_host_rsa_key >> /etc/ssh/sshd_config
echo HostKey /etc/ssh/ssh_host_dsa_key >> /etc/ssh/sshd_config
fi
%triggerpostun server -- ssh-server
if [ "$1" != 0 ] ; then
/sbin/chkconfig --add sshd
if test -f /var/run/sshd.restart ; then
rm -f /var/run/sshd.restart
/sbin/service sshd start > /dev/null 2>&1 || :
fi
fi
%pre server
%{_sbindir}/groupadd -r -g %{sshd_gid} sshd 2>/dev/null || :
%{_sbindir}/useradd -d /var/empty/sshd -s /bin/false -u %{sshd_uid} \
-g sshd -M -r sshd 2>/dev/null || :
%post server
/sbin/chkconfig --add sshd
%postun server
/sbin/service sshd condrestart > /dev/null 2>&1 || :
%preun server
if [ "$1" = 0 ]
then
/sbin/service sshd stop > /dev/null 2>&1 || :
/sbin/chkconfig --del sshd
fi
%files
%defattr(-,root,root)
%doc CREDITS ChangeLog INSTALL LICENCE OVERVIEW README* PROTOCOL* TODO
%attr(0755,root,root) %{_bindir}/scp
%attr(0644,root,root) %{_mandir}/man1/scp.1*
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli
%if ! %{rescue}
%attr(0755,root,root) %{_bindir}/ssh-keygen
%attr(0644,root,root) %{_mandir}/man1/ssh-keygen.1*
%attr(0755,root,root) %dir %{_libexecdir}/openssh
%attr(4711,root,root) %{_libexecdir}/openssh/ssh-keysign
%attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper
%attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8*
%attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8*
%endif
%if %{scard}
%attr(0755,root,root) %dir %{_datadir}/openssh
%attr(0644,root,root) %{_datadir}/openssh/Ssh.bin
%endif
%files clients
%defattr(-,root,root)
%attr(0755,root,root) %{_bindir}/ssh
%attr(0644,root,root) %{_mandir}/man1/ssh.1*
%attr(0644,root,root) %{_mandir}/man5/ssh_config.5*
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config
%if ! %{rescue}
%attr(2755,root,nobody) %{_bindir}/ssh-agent
%attr(0755,root,root) %{_bindir}/ssh-add
%attr(0755,root,root) %{_bindir}/ssh-keyscan
%attr(0755,root,root) %{_bindir}/sftp
%attr(0644,root,root) %{_mandir}/man1/ssh-agent.1*
%attr(0644,root,root) %{_mandir}/man1/ssh-add.1*
%attr(0644,root,root) %{_mandir}/man1/ssh-keyscan.1*
%attr(0644,root,root) %{_mandir}/man1/sftp.1*
%endif
%if ! %{rescue}
%files server
%defattr(-,root,root)
%dir %attr(0111,root,root) %{_var}/empty/sshd
%attr(0755,root,root) %{_sbindir}/sshd
%attr(0755,root,root) %{_libexecdir}/openssh/sftp-server
%attr(0644,root,root) %{_mandir}/man8/sshd.8*
%attr(0644,root,root) %{_mandir}/man5/moduli.5*
%attr(0644,root,root) %{_mandir}/man5/sshd_config.5*
%attr(0644,root,root) %{_mandir}/man8/sftp-server.8*
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config
%attr(0600,root,root) %config(noreplace) /etc/pam.d/sshd
%attr(0755,root,root) %config /etc/rc.d/init.d/sshd
%endif
%if ! %{no_x11_askpass}
%files askpass
%defattr(-,root,root)
%doc x11-ssh-askpass-%{aversion}/README
%doc x11-ssh-askpass-%{aversion}/ChangeLog
%doc x11-ssh-askpass-%{aversion}/SshAskpass*.ad
%{_libexecdir}/openssh/ssh-askpass
%attr(0755,root,root) %{_libexecdir}/openssh/x11-ssh-askpass
%endif
%if ! %{no_gnome_askpass}
%files askpass-gnome
%defattr(-,root,root)
%attr(0755,root,root) %config %{_sysconfdir}/profile.d/gnome-ssh-askpass.*
%attr(0755,root,root) %{_libexecdir}/openssh/gnome-ssh-askpass
%endif
%changelog
* Sat Feb 10 2018 Darren Tucker <dtucker@dtucker.net>
- Update openssl-devel dependency to match current requirements.
- Handle Fedora >=6 openssl 1.0 compat libs.
- Remove SSH1 from description.
- Don't strip binaries at build time so that debuginfo package can be
created.
* Sun Nov 16 2014 Nico Kadel-Garcia <nakdel@gmail.com>
- Add '--mandir' and '--with-mantype' for RHEL 5 compatibility
- Add 'dist' option to 'ver' so package names reflect OS at build time
- Always include x11-ssh-askpass tarball in SRPM
- Add openssh-x11-aspass BuildRequires for libXT-devel, imake, gtk2-devel
- Discard 'K5DIR' reporting, not usable inside 'mock' for RHEL 5 compatibility
- Discard obsolete '--with-rsh' configure option
- Update openssl-devel dependency to 0.9.8f, as found in autoconf
* Wed Jul 14 2010 Tim Rice <tim@multitalents.net>
- test for skip_x11_askpass (line 77) should have been for no_x11_askpass
* Mon Jun 2 2003 Damien Miller <djm@mindrot.org>
- Remove noip6 option. This may be controlled at run-time in client config
file using new AddressFamily directive
* Mon May 12 2003 Damien Miller <djm@mindrot.org>
- Don't install profile.d scripts when not building with GNOME/GTK askpass
(patch from bet@rahul.net)
* Tue Oct 01 2002 Damien Miller <djm@mindrot.org>
- Install ssh-agent setgid nobody to prevent ptrace() key theft attacks
* Mon Sep 30 2002 Damien Miller <djm@mindrot.org>
- Use contrib/ Makefile for building askpass programs
* Fri Jun 21 2002 Damien Miller <djm@mindrot.org>
- Merge in spec changes from seba@iq.pl (Sebastian Pachuta)
- Add new {ssh,sshd}_config.5 manpages
- Add new ssh-keysign program and remove setuid from ssh client
* Fri May 10 2002 Damien Miller <djm@mindrot.org>
- Merge in spec changes from RedHat, reorgansie a little
- Add Privsep user, group and directory
* Thu Mar 7 2002 Nalin Dahyabhai <nalin@redhat.com> 3.1p1-2
- bump and grind (through the build system)
* Thu Mar 7 2002 Nalin Dahyabhai <nalin@redhat.com> 3.1p1-1
- require sharutils for building (mindrot #137)
- require db1-devel only when building for 6.x (#55105), which probably won't
work anyway (3.1 requires OpenSSL 0.9.6 to build), but what the heck
- require pam-devel by file (not by package name) again
- add Markus's patch to compile with OpenSSL 0.9.5a (from
http://bugzilla.mindrot.org/show_bug.cgi?id=141) and apply it if we're
building for 6.x
* Thu Mar 7 2002 Nalin Dahyabhai <nalin@redhat.com> 3.1p1-0
- update to 3.1p1
* Tue Mar 5 2002 Nalin Dahyabhai <nalin@redhat.com> SNAP-20020305
- update to SNAP-20020305
- drop debug patch, fixed upstream
* Wed Feb 20 2002 Nalin Dahyabhai <nalin@redhat.com> SNAP-20020220
- update to SNAP-20020220 for testing purposes (you've been warned, if there's
anything to be warned about, gss patches won't apply, I don't mind)
* Wed Feb 13 2002 Nalin Dahyabhai <nalin@redhat.com> 3.0.2p1-3
- add patches from Simon Wilkinson and Nicolas Williams for GSSAPI key
exchange, authentication, and named key support
* Wed Jan 23 2002 Nalin Dahyabhai <nalin@redhat.com> 3.0.2p1-2
- remove dependency on db1-devel, which has just been swallowed up whole
by gnome-libs-devel
* Sat Dec 29 2001 Nalin Dahyabhai <nalin@redhat.com>
- adjust build dependencies so that build6x actually works right (fix
from Hugo van der Kooij)
* Tue Dec 4 2001 Nalin Dahyabhai <nalin@redhat.com> 3.0.2p1-1
- update to 3.0.2p1
* Fri Nov 16 2001 Nalin Dahyabhai <nalin@redhat.com> 3.0.1p1-1
- update to 3.0.1p1
* Tue Nov 13 2001 Nalin Dahyabhai <nalin@redhat.com>
- update to current CVS (not for use in distribution)
* Thu Nov 8 2001 Nalin Dahyabhai <nalin@redhat.com> 3.0p1-1
- merge some of Damien Miller <djm@mindrot.org> changes from the upstream
3.0p1 spec file and init script
* Wed Nov 7 2001 Nalin Dahyabhai <nalin@redhat.com>
- update to 3.0p1
- update to x11-ssh-askpass 1.2.4.1
- change build dependency on a file from pam-devel to the pam-devel package
- replace primes with moduli
* Thu Sep 27 2001 Nalin Dahyabhai <nalin@redhat.com> 2.9p2-9
- incorporate fix from Markus Friedl's advisory for IP-based authorization bugs
* Thu Sep 13 2001 Bernhard Rosenkraenzer <bero@redhat.com> 2.9p2-8
- Merge changes to rescue build from current sysadmin survival cd
* Thu Sep 6 2001 Nalin Dahyabhai <nalin@redhat.com> 2.9p2-7
- fix scp's server's reporting of file sizes, and build with the proper
preprocessor define to get large-file capable open(), stat(), etc.
(sftp has been doing this correctly all along) (#51827)
- configure without --with-ipv4-default on RHL 7.x and newer (#45987,#52247)
- pull cvs patch to fix support for /etc/nologin for non-PAM logins (#47298)
- mark profile.d scriptlets as config files (#42337)
- refer to Jason Stone's mail for zsh workaround for exit-hanging quasi-bug
- change a couple of log() statements to debug() statements (#50751)
- pull cvs patch to add -t flag to sshd (#28611)
- clear fd_sets correctly (one bit per FD, not one byte per FD) (#43221)
* Mon Aug 20 2001 Nalin Dahyabhai <nalin@redhat.com> 2.9p2-6
- add db1-devel as a BuildPrerequisite (noted by Hans Ecke)
* Thu Aug 16 2001 Nalin Dahyabhai <nalin@redhat.com>
- pull cvs patch to fix remote port forwarding with protocol 2
* Thu Aug 9 2001 Nalin Dahyabhai <nalin@redhat.com>
- pull cvs patch to add session initialization to no-pty sessions
- pull cvs patch to not cut off challengeresponse auth needlessly
- refuse to do X11 forwarding if xauth isn't there, handy if you enable
it by default on a system that doesn't have X installed (#49263)
* Wed Aug 8 2001 Nalin Dahyabhai <nalin@redhat.com>
- don't apply patches to code we don't intend to build (spotted by Matt Galgoci)
* Mon Aug 6 2001 Nalin Dahyabhai <nalin@redhat.com>
- pass OPTIONS correctly to initlog (#50151)
* Wed Jul 25 2001 Nalin Dahyabhai <nalin@redhat.com>
- switch to x11-ssh-askpass 1.2.2
* Wed Jul 11 2001 Nalin Dahyabhai <nalin@redhat.com>
- rebuild in new environment
* Mon Jun 25 2001 Nalin Dahyabhai <nalin@redhat.com>
- disable the gssapi patch
* Mon Jun 18 2001 Nalin Dahyabhai <nalin@redhat.com>
- update to 2.9p2
- refresh to a new version of the gssapi patch
* Thu Jun 7 2001 Nalin Dahyabhai <nalin@redhat.com>
- change Copyright: BSD to License: BSD
- add Markus Friedl's unverified patch for the cookie file deletion problem
so that we can verify it
- drop patch to check if xauth is present (was folded into cookie patch)
- don't apply gssapi patches for the errata candidate
- clear supplemental groups list at startup
* Fri May 25 2001 Nalin Dahyabhai <nalin@redhat.com>
- fix an error parsing the new default sshd_config
- add a fix from Markus Friedl (via openssh-unix-dev) for ssh-keygen not
dealing with comments right
* Thu May 24 2001 Nalin Dahyabhai <nalin@redhat.com>
- add in Simon Wilkinson's GSSAPI patch to give it some testing in-house,
to be removed before the next beta cycle because it's a big departure
from the upstream version
* Thu May 3 2001 Nalin Dahyabhai <nalin@redhat.com>
- finish marking strings in the init script for translation
- modify init script to source /etc/sysconfig/sshd and pass $OPTIONS to sshd
at startup (change merged from openssh.com init script, originally by
Pekka Savola)
- refuse to do X11 forwarding if xauth isn't there, handy if you enable
it by default on a system that doesn't have X installed
* Wed May 2 2001 Nalin Dahyabhai <nalin@redhat.com>
- update to 2.9
- drop various patches that came from or went upstream or to or from CVS
* Wed Apr 18 2001 Nalin Dahyabhai <nalin@redhat.com>
- only require initscripts 5.00 on 6.2 (reported by Peter Bieringer)
* Sun Apr 8 2001 Preston Brown <pbrown@redhat.com>
- remove explicit openssl requirement, fixes builddistro issue
- make initscript stop() function wait until sshd really dead to avoid
races in condrestart
* Mon Apr 2 2001 Nalin Dahyabhai <nalin@redhat.com>
- mention that challengereponse supports PAM, so disabling password doesn't
limit users to pubkey and rsa auth (#34378)
- bypass the daemon() function in the init script and call initlog directly,
because daemon() won't start a daemon it detects is already running (like
open connections)
- require the version of openssl we had when we were built
* Fri Mar 23 2001 Nalin Dahyabhai <nalin@redhat.com>
- make do_pam_setcred() smart enough to know when to establish creds and
when to reinitialize them
- add in a couple of other fixes from Damien for inclusion in the errata
* Thu Mar 22 2001 Nalin Dahyabhai <nalin@redhat.com>
- update to 2.5.2p2
- call setcred() again after initgroups, because the "creds" could actually
be group memberships
* Tue Mar 20 2001 Nalin Dahyabhai <nalin@redhat.com>
- update to 2.5.2p1 (includes endianness fixes in the rijndael implementation)
- don't enable challenge-response by default until we find a way to not
have too many userauth requests (we may make up to six pubkey and up to
three password attempts as it is)
- remove build dependency on rsh to match openssh.com's packages more closely
* Sat Mar 3 2001 Nalin Dahyabhai <nalin@redhat.com>
- remove dependency on openssl -- would need to be too precise
* Fri Mar 2 2001 Nalin Dahyabhai <nalin@redhat.com>
- rebuild in new environment
* Mon Feb 26 2001 Nalin Dahyabhai <nalin@redhat.com>
- Revert the patch to move pam_open_session.
- Init script and spec file changes from Pekka Savola. (#28750)
- Patch sftp to recognize '-o protocol' arguments. (#29540)
* Thu Feb 22 2001 Nalin Dahyabhai <nalin@redhat.com>
- Chuck the closing patch.
- Add a trigger to add host keys for protocol 2 to the config file, now that
configuration file syntax requires us to specify it with HostKey if we
specify any other HostKey values, which we do.
* Tue Feb 20 2001 Nalin Dahyabhai <nalin@redhat.com>
- Redo patch to move pam_open_session after the server setuid()s to the user.
- Rework the nopam patch to use be picked up by autoconf.
* Mon Feb 19 2001 Nalin Dahyabhai <nalin@redhat.com>
- Update for 2.5.1p1.
- Add init script mods from Pekka Savola.
- Tweak the init script to match the CVS contrib script more closely.
- Redo patch to ssh-add to try to adding both identity and id_dsa to also try
adding id_rsa.
* Fri Feb 16 2001 Nalin Dahyabhai <nalin@redhat.com>
- Update for 2.5.0p1.
- Use $RPM_OPT_FLAGS instead of -O when building gnome-ssh-askpass
- Resync with parts of Damien Miller's openssh.spec from CVS, including
update of x11 askpass to 1.2.0.
- Only require openssl (don't prereq) because we generate keys in the init
script now.
* Tue Feb 13 2001 Nalin Dahyabhai <nalin@redhat.com>
- Don't open a PAM session until we've forked and become the user (#25690).
- Apply Andrew Bartlett's patch for letting pam_authenticate() know which
host the user is attempting a login from.
- Resync with parts of Damien Miller's openssh.spec from CVS.
- Don't expose KbdInt responses in debug messages (from CVS).
- Detect and handle errors in rsa_{public,private}_decrypt (from CVS).
* Wed Feb 7 2001 Trond Eivind Glomsrxd <teg@redhat.com>
- i18n-tweak to initscript.
* Tue Jan 23 2001 Nalin Dahyabhai <nalin@redhat.com>
- More gettextizing.
- Close all files after going into daemon mode (needs more testing).
- Extract patch from CVS to handle auth banners (in the client).
- Extract patch from CVS to handle compat weirdness.
* Fri Jan 19 2001 Nalin Dahyabhai <nalin@redhat.com>
- Finish with the gettextizing.
* Thu Jan 18 2001 Nalin Dahyabhai <nalin@redhat.com>
- Fix a bug in auth2-pam.c (#23877)
- Gettextize the init script.
* Wed Dec 20 2000 Nalin Dahyabhai <nalin@redhat.com>
- Incorporate a switch for using PAM configs for 6.x, just in case.
* Tue Dec 5 2000 Nalin Dahyabhai <nalin@redhat.com>
- Incorporate Bero's changes for a build specifically for rescue CDs.
* Wed Nov 29 2000 Nalin Dahyabhai <nalin@redhat.com>
- Don't treat pam_setcred() failure as fatal unless pam_authenticate() has
succeeded, to allow public-key authentication after a failure with "none"
authentication. (#21268)
* Tue Nov 28 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to x11-askpass 1.1.1. (#21301)
- Don't second-guess fixpaths, which causes paths to get fixed twice. (#21290)
* Mon Nov 27 2000 Nalin Dahyabhai <nalin@redhat.com>
- Merge multiple PAM text messages into subsequent prompts when possible when
doing keyboard-interactive authentication.
* Sun Nov 26 2000 Nalin Dahyabhai <nalin@redhat.com>
- Disable the built-in MD5 password support. We're using PAM.
- Take a crack at doing keyboard-interactive authentication with PAM, and
enable use of it in the default client configuration so that the client
will try it when the server disallows password authentication.
- Build with debugging flags. Build root policies strip all binaries anyway.
* Tue Nov 21 2000 Nalin Dahyabhai <nalin@redhat.com>
- Use DESTDIR instead of %%makeinstall.
- Remove /usr/X11R6/bin from the path-fixing patch.
* Mon Nov 20 2000 Nalin Dahyabhai <nalin@redhat.com>
- Add the primes file from the latest snapshot to the main package (#20884).
- Add the dev package to the prereq list (#19984).
- Remove the default path and mimic login's behavior in the server itself.
* Fri Nov 17 2000 Nalin Dahyabhai <nalin@redhat.com>
- Resync with conditional options in Damien Miller's .spec file for an errata.
- Change libexecdir from %%{_libexecdir}/ssh to %%{_libexecdir}/openssh.
* Tue Nov 7 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to OpenSSH 2.3.0p1.
- Update to x11-askpass 1.1.0.
- Enable keyboard-interactive authentication.
* Mon Oct 30 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to ssh-askpass-x11 1.0.3.
- Change authentication related messages to be private (#19966).
* Tue Oct 10 2000 Nalin Dahyabhai <nalin@redhat.com>
- Patch ssh-keygen to be able to list signatures for DSA public key files
it generates.
* Thu Oct 5 2000 Nalin Dahyabhai <nalin@redhat.com>
- Add BuildRequires on /usr/include/security/pam_appl.h to be sure we always
build PAM authentication in.
- Try setting SSH_ASKPASS if gnome-ssh-askpass is installed.
- Clean out no-longer-used patches.
- Patch ssh-add to try to add both identity and id_dsa, and to error only
when neither exists.
* Mon Oct 2 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update x11-askpass to 1.0.2. (#17835)
- Add BuildRequiress for /bin/login and /usr/bin/rsh so that configure will
always find them in the right place. (#17909)
- Set the default path to be the same as the one supplied by /bin/login, but
add /usr/X11R6/bin. (#17909)
- Try to handle obsoletion of ssh-server more cleanly. Package names
are different, but init script name isn't. (#17865)
* Wed Sep 6 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to 2.2.0p1. (#17835)
- Tweak the init script to allow proper restarting. (#18023)
* Wed Aug 23 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to 20000823 snapshot.
- Change subpackage requirements from %%{version} to %%{version}-%%{release}
- Back out the pipe patch.
* Mon Jul 17 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to 2.1.1p4, which includes fixes for config file parsing problems.
- Move the init script back.
- Add Damien's quick fix for wackiness.
* Wed Jul 12 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to 2.1.1p3, which includes fixes for X11 forwarding and strtok().
* Thu Jul 6 2000 Nalin Dahyabhai <nalin@redhat.com>
- Move condrestart to server postun.
- Move key generation to init script.
- Actually use the right patch for moving the key generation to the init script.
- Clean up the init script a bit.
* Wed Jul 5 2000 Nalin Dahyabhai <nalin@redhat.com>
- Fix X11 forwarding, from mail post by Chan Shih-Ping Richard.
* Sun Jul 2 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to 2.1.1p2.
- Use of strtok() considered harmful.
* Sat Jul 1 2000 Nalin Dahyabhai <nalin@redhat.com>
- Get the build root out of the man pages.
* Thu Jun 29 2000 Nalin Dahyabhai <nalin@redhat.com>
- Add and use condrestart support in the init script.
- Add newer initscripts as a prereq.
* Tue Jun 27 2000 Nalin Dahyabhai <nalin@redhat.com>
- Build in new environment (release 2)
- Move -clients subpackage to Applications/Internet group
* Fri Jun 9 2000 Nalin Dahyabhai <nalin@redhat.com>
- Update to 2.2.1p1
* Sat Jun 3 2000 Nalin Dahyabhai <nalin@redhat.com>
- Patch to build with neither RSA nor RSAref.
- Miscellaneous FHS-compliance tweaks.
- Fix for possibly-compressed man pages.
* Wed Mar 15 2000 Damien Miller <djm@ibs.com.au>
- Updated for new location
- Updated for new gnome-ssh-askpass build
* Sun Dec 26 1999 Damien Miller <djm@mindrot.org>
- Added Jim Knoble's <jmknoble@pobox.com> askpass
* Mon Nov 15 1999 Damien Miller <djm@mindrot.org>
- Split subpackages further based on patch from jim knoble <jmknoble@pobox.com>
* Sat Nov 13 1999 Damien Miller <djm@mindrot.org>
- Added 'Obsoletes' directives
* Tue Nov 09 1999 Damien Miller <djm@ibs.com.au>
- Use make install
- Subpackages
* Mon Nov 08 1999 Damien Miller <djm@ibs.com.au>
- Added links for slogin
- Fixed perms on manpages
* Sat Oct 30 1999 Damien Miller <djm@ibs.com.au>
- Renamed init script
* Fri Oct 29 1999 Damien Miller <djm@ibs.com.au>
- Back to old binary names
* Thu Oct 28 1999 Damien Miller <djm@ibs.com.au>
- Use autoconf
- New binary names
* Wed Oct 27 1999 Damien Miller <djm@ibs.com.au>
- Initial RPMification, based on Jan "Yenya" Kasprzak's <kas@fi.muni.cz> spec.
diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec
index b43d8985abaf..4788718156a4 100644
--- a/contrib/suse/openssh.spec
+++ b/contrib/suse/openssh.spec
@@ -1,241 +1,241 @@
# Default values for additional components
%define build_x11_askpass 1
# Define the UID/GID to use for privilege separation
%define sshd_gid 65
%define sshd_uid 71
# The version of x11-ssh-askpass to use
%define xversion 1.2.4.1
# Allow the ability to override defaults with -D skip_xxx=1
%{?skip_x11_askpass:%define build_x11_askpass 0}
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh
-Version: 7.9p1
+Version: 8.0p1
URL: https://www.openssh.com/
Release: 1
Source0: openssh-%{version}.tar.gz
Source1: x11-ssh-askpass-%{xversion}.tar.gz
License: BSD
Group: Productivity/Networking/SSH
BuildRoot: %{_tmppath}/openssh-%{version}-buildroot
PreReq: openssl
Obsoletes: ssh
Provides: ssh
#
# (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.)
# building prerequisites -- stuff for
# OpenSSL (openssl-devel),
# and Gnome (glibdev, gtkdev, and gnlibsd)
#
BuildPrereq: openssl
BuildPrereq: zlib-devel
#BuildPrereq: glibdev
#BuildPrereq: gtkdev
#BuildPrereq: gnlibsd
%package askpass
Summary: A passphrase dialog for OpenSSH and the X window System.
Group: Productivity/Networking/SSH
Requires: openssh = %{version}
Obsoletes: ssh-extras
Provides: openssh:${_libdir}/ssh/ssh-askpass
%if %{build_x11_askpass}
BuildPrereq: XFree86-devel
%endif
%description
Ssh (Secure Shell) is a program for logging into a remote machine and for
executing commands in a remote machine. It is intended to replace
rlogin and rsh, and provide secure encrypted communications between
two untrusted hosts over an insecure network. X11 connections and
arbitrary TCP/IP ports can also be forwarded over the secure channel.
OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it
up to date in terms of security and features, as well as removing all
patented algorithms to separate libraries (OpenSSL).
This package includes all files necessary for both the OpenSSH
client and server.
%description askpass
Ssh (Secure Shell) is a program for logging into a remote machine and for
executing commands in a remote machine. It is intended to replace
rlogin and rsh, and provide secure encrypted communications between
two untrusted hosts over an insecure network. X11 connections and
arbitrary TCP/IP ports can also be forwarded over the secure channel.
OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it
up to date in terms of security and features, as well as removing all
patented algorithms to separate libraries (OpenSSL).
This package contains an X Window System passphrase dialog for OpenSSH.
%changelog
* Wed Oct 26 2005 Iain Morgan <imorgan@nas.nasa.gov>
- Removed accidental inclusion of --without-zlib-version-check
* Tue Oct 25 2005 Iain Morgan <imorgan@nas.nasa.gov>
- Overhaul to deal with newer versions of SuSE and OpenSSH
* Mon Jun 12 2000 Damien Miller <djm@mindrot.org>
- Glob manpages to catch compressed files
* Wed Mar 15 2000 Damien Miller <djm@ibs.com.au>
- Updated for new location
- Updated for new gnome-ssh-askpass build
* Sun Dec 26 1999 Chris Saia <csaia@wtower.com>
- Made symlink to gnome-ssh-askpass called ssh-askpass
* Wed Nov 24 1999 Chris Saia <csaia@wtower.com>
- Removed patches that included /etc/pam.d/sshd, /sbin/init.d/rc.sshd, and
/var/adm/fillup-templates/rc.config.sshd, since Damien merged these into
his released tarfile
- Changed permissions on ssh_config in the install procedure to 644 from 600
even though it was correct in the %files section and thus right in the RPMs
- Postinstall script for the server now only prints "Generating SSH host
key..." if we need to actually do this, in order to eliminate a confusing
message if an SSH host key is already in place
- Marked all manual pages as %doc(umentation)
* Mon Nov 22 1999 Chris Saia <csaia@wtower.com>
- Added flag to configure daemon with TCP Wrappers support
- Added building prerequisites (works in RPM 3.0 and newer)
* Thu Nov 18 1999 Chris Saia <csaia@wtower.com>
- Made this package correct for SuSE.
- Changed instances of pam_pwdb.so to pam_unix.so, since it works more properly
with SuSE, and lib_pwdb.so isn't installed by default.
* Mon Nov 15 1999 Damien Miller <djm@mindrot.org>
- Split subpackages further based on patch from jim knoble <jmknoble@pobox.com>
* Sat Nov 13 1999 Damien Miller <djm@mindrot.org>
- Added 'Obsoletes' directives
* Tue Nov 09 1999 Damien Miller <djm@ibs.com.au>
- Use make install
- Subpackages
* Mon Nov 08 1999 Damien Miller <djm@ibs.com.au>
- Added links for slogin
- Fixed perms on manpages
* Sat Oct 30 1999 Damien Miller <djm@ibs.com.au>
- Renamed init script
* Fri Oct 29 1999 Damien Miller <djm@ibs.com.au>
- Back to old binary names
* Thu Oct 28 1999 Damien Miller <djm@ibs.com.au>
- Use autoconf
- New binary names
* Wed Oct 27 1999 Damien Miller <djm@ibs.com.au>
- Initial RPMification, based on Jan "Yenya" Kasprzak's <kas@fi.muni.cz> spec.
%prep
%if %{build_x11_askpass}
%setup -q -a 1
%else
%setup -q
%endif
%build
CFLAGS="$RPM_OPT_FLAGS" \
%configure --prefix=/usr \
--sysconfdir=%{_sysconfdir}/ssh \
--mandir=%{_mandir} \
--with-privsep-path=/var/lib/empty \
--with-pam \
--libexecdir=%{_libdir}/ssh
make
%if %{build_x11_askpass}
cd x11-ssh-askpass-%{xversion}
%configure --mandir=/usr/X11R6/man \
--libexecdir=%{_libdir}/ssh
xmkmf -a
make
cd ..
%endif
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT/
install -d $RPM_BUILD_ROOT/etc/pam.d/
install -d $RPM_BUILD_ROOT/etc/init.d/
install -d $RPM_BUILD_ROOT/var/adm/fillup-templates
install -m644 contrib/sshd.pam.generic $RPM_BUILD_ROOT/etc/pam.d/sshd
install -m744 contrib/suse/rc.sshd $RPM_BUILD_ROOT/etc/init.d/sshd
install -m744 contrib/suse/sysconfig.ssh \
$RPM_BUILD_ROOT/var/adm/fillup-templates
%if %{build_x11_askpass}
cd x11-ssh-askpass-%{xversion}
make install install.man BINDIR=%{_libdir}/ssh DESTDIR=$RPM_BUILD_ROOT/
rm -f $RPM_BUILD_ROOT/usr/share/Ssh.bin
%endif
%clean
rm -rf $RPM_BUILD_ROOT
%pre
/usr/sbin/groupadd -g %{sshd_gid} -o -r sshd 2> /dev/null || :
/usr/sbin/useradd -r -o -g sshd -u %{sshd_uid} -s /bin/false -c "SSH Privilege Separation User" -d /var/lib/sshd sshd 2> /dev/null || :
%post
/usr/bin/ssh-keygen -A
%{fillup_and_insserv -n -y ssh sshd}
%run_permissions
%verifyscript
%verify_permissions -e /etc/ssh/sshd_config -e /etc/ssh/ssh_config -e /usr/bin/ssh
%preun
%stop_on_removal sshd
%postun
%restart_on_update sshd
%{insserv_cleanup}
%files
%defattr(-,root,root)
%doc ChangeLog OVERVIEW README* PROTOCOL*
%doc TODO CREDITS LICENCE
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli
%attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd
%attr(0755,root,root) %config /etc/init.d/sshd
%attr(0755,root,root) %{_bindir}/ssh-keygen
%attr(0755,root,root) %{_bindir}/scp
%attr(0755,root,root) %{_bindir}/ssh
%attr(0755,root,root) %{_bindir}/ssh-agent
%attr(0755,root,root) %{_bindir}/ssh-add
%attr(0755,root,root) %{_bindir}/ssh-keyscan
%attr(0755,root,root) %{_bindir}/sftp
%attr(0755,root,root) %{_sbindir}/sshd
%attr(0755,root,root) %dir %{_libdir}/ssh
%attr(0755,root,root) %{_libdir}/ssh/sftp-server
%attr(4711,root,root) %{_libdir}/ssh/ssh-keysign
%attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper
%attr(0644,root,root) %doc %{_mandir}/man1/scp.1*
%attr(0644,root,root) %doc %{_mandir}/man1/sftp.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-add.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keygen.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh-keyscan.1*
%attr(0644,root,root) %doc %{_mandir}/man5/moduli.5*
%attr(0644,root,root) %doc %{_mandir}/man5/ssh_config.5*
%attr(0644,root,root) %doc %{_mandir}/man5/sshd_config.5*
%attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8*
%attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8*
%attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8*
%attr(0644,root,root) %doc %{_mandir}/man8/sshd.8*
%attr(0644,root,root) /var/adm/fillup-templates/sysconfig.ssh
%if %{build_x11_askpass}
%files askpass
%defattr(-,root,root)
%doc x11-ssh-askpass-%{xversion}/README
%doc x11-ssh-askpass-%{xversion}/ChangeLog
%doc x11-ssh-askpass-%{xversion}/SshAskpass*.ad
%attr(0755,root,root) %{_libdir}/ssh/ssh-askpass
%attr(0755,root,root) %{_libdir}/ssh/x11-ssh-askpass
%attr(0644,root,root) %doc /usr/X11R6/man/man1/ssh-askpass.1x*
%attr(0644,root,root) %doc /usr/X11R6/man/man1/x11-ssh-askpass.1x*
%attr(0644,root,root) %config /usr/X11R6/lib/X11/app-defaults/SshAskpass
%endif
diff --git a/crypto_api.h b/crypto_api.h
index 7f45bbd69e77..eb05251ff164 100644
--- a/crypto_api.h
+++ b/crypto_api.h
@@ -1,40 +1,56 @@
-/* $OpenBSD: crypto_api.h,v 1.4 2017/12/14 21:07:39 naddy Exp $ */
+/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */
/*
* Assembled from generated headers and source files by Markus Friedl.
* Placed in the public domain.
*/
#ifndef crypto_api_h
#define crypto_api_h
#include "includes.h"
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
+typedef int8_t crypto_int8;
+typedef uint8_t crypto_uint8;
+typedef int16_t crypto_int16;
+typedef uint16_t crypto_uint16;
typedef int32_t crypto_int32;
typedef uint32_t crypto_uint32;
#define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len))
+#define small_random32() arc4random()
#define crypto_hash_sha512_BYTES 64U
int crypto_hash_sha512(unsigned char *, const unsigned char *,
unsigned long long);
int crypto_verify_32(const unsigned char *, const unsigned char *);
#define crypto_sign_ed25519_SECRETKEYBYTES 64U
#define crypto_sign_ed25519_PUBLICKEYBYTES 32U
#define crypto_sign_ed25519_BYTES 64U
int crypto_sign_ed25519(unsigned char *, unsigned long long *,
const unsigned char *, unsigned long long, const unsigned char *);
int crypto_sign_ed25519_open(unsigned char *, unsigned long long *,
const unsigned char *, unsigned long long, const unsigned char *);
int crypto_sign_ed25519_keypair(unsigned char *, unsigned char *);
+#define crypto_kem_sntrup4591761_PUBLICKEYBYTES 1218
+#define crypto_kem_sntrup4591761_SECRETKEYBYTES 1600
+#define crypto_kem_sntrup4591761_CIPHERTEXTBYTES 1047
+#define crypto_kem_sntrup4591761_BYTES 32
+
+int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k,
+ const unsigned char *pk);
+int crypto_kem_sntrup4591761_dec(unsigned char *k,
+ const unsigned char *cstr, const unsigned char *sk);
+int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk);
+
#endif /* crypto_api_h */
diff --git a/dh.c b/dh.c
index 657b32da3d98..a98d39ed5ff4 100644
--- a/dh.c
+++ b/dh.c
@@ -1,492 +1,492 @@
-/* $OpenBSD: dh.c,v 1.68 2018/09/17 15:40:14 millert Exp $ */
+/* $OpenBSD: dh.c,v 1.69 2018/11/09 02:56:22 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "dh.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "ssherr.h"
#include "openbsd-compat/openssl-compat.h"
static int
parse_prime(int linenum, char *line, struct dhgroup *dhg)
{
char *cp, *arg;
char *strsize, *gen, *prime;
const char *errstr = NULL;
long long n;
dhg->p = dhg->g = NULL;
cp = line;
if ((arg = strdelim(&cp)) == NULL)
return 0;
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!arg || !*arg || *arg == '#')
return 0;
/* time */
if (cp == NULL || *arg == '\0')
goto truncated;
arg = strsep(&cp, " "); /* type */
if (cp == NULL || *arg == '\0')
goto truncated;
/* Ensure this is a safe prime */
n = strtonum(arg, 0, 5, &errstr);
if (errstr != NULL || n != MODULI_TYPE_SAFE) {
error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
goto fail;
}
arg = strsep(&cp, " "); /* tests */
if (cp == NULL || *arg == '\0')
goto truncated;
/* Ensure prime has been tested and is not composite */
n = strtonum(arg, 0, 0x1f, &errstr);
if (errstr != NULL ||
(n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
error("moduli:%d: invalid moduli tests flag", linenum);
goto fail;
}
arg = strsep(&cp, " "); /* tries */
if (cp == NULL || *arg == '\0')
goto truncated;
n = strtonum(arg, 0, 1<<30, &errstr);
if (errstr != NULL || n == 0) {
error("moduli:%d: invalid primality trial count", linenum);
goto fail;
}
strsize = strsep(&cp, " "); /* size */
if (cp == NULL || *strsize == '\0' ||
(dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
errstr) {
error("moduli:%d: invalid prime length", linenum);
goto fail;
}
/* The whole group is one bit larger */
dhg->size++;
gen = strsep(&cp, " "); /* gen */
if (cp == NULL || *gen == '\0')
goto truncated;
prime = strsep(&cp, " "); /* prime */
if (cp != NULL || *prime == '\0') {
truncated:
error("moduli:%d: truncated", linenum);
goto fail;
}
if ((dhg->g = BN_new()) == NULL ||
(dhg->p = BN_new()) == NULL) {
error("parse_prime: BN_new failed");
goto fail;
}
if (BN_hex2bn(&dhg->g, gen) == 0) {
error("moduli:%d: could not parse generator value", linenum);
goto fail;
}
if (BN_hex2bn(&dhg->p, prime) == 0) {
error("moduli:%d: could not parse prime value", linenum);
goto fail;
}
if (BN_num_bits(dhg->p) != dhg->size) {
error("moduli:%d: prime has wrong size: actual %d listed %d",
linenum, BN_num_bits(dhg->p), dhg->size - 1);
goto fail;
}
if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
error("moduli:%d: generator is invalid", linenum);
goto fail;
}
return 1;
fail:
BN_clear_free(dhg->g);
BN_clear_free(dhg->p);
dhg->g = dhg->p = NULL;
return 0;
}
DH *
choose_dh(int min, int wantbits, int max)
{
FILE *f;
char *line = NULL;
size_t linesize = 0;
int best, bestcount, which, linenum;
struct dhgroup dhg;
if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
logit("WARNING: could not open %s (%s), using fixed modulus",
_PATH_DH_MODULI, strerror(errno));
return (dh_new_group_fallback(max));
}
linenum = 0;
best = bestcount = 0;
while (getline(&line, &linesize, f) != -1) {
linenum++;
if (!parse_prime(linenum, line, &dhg))
continue;
BN_clear_free(dhg.g);
BN_clear_free(dhg.p);
if (dhg.size > max || dhg.size < min)
continue;
if ((dhg.size > wantbits && dhg.size < best) ||
(dhg.size > best && best < wantbits)) {
best = dhg.size;
bestcount = 0;
}
if (dhg.size == best)
bestcount++;
}
free(line);
line = NULL;
linesize = 0;
rewind(f);
if (bestcount == 0) {
fclose(f);
logit("WARNING: no suitable primes in %s", _PATH_DH_MODULI);
return (dh_new_group_fallback(max));
}
which = arc4random_uniform(bestcount);
linenum = 0;
bestcount = 0;
while (getline(&line, &linesize, f) != -1) {
linenum++;
if (!parse_prime(linenum, line, &dhg))
continue;
if ((dhg.size > max || dhg.size < min) ||
dhg.size != best ||
bestcount++ != which) {
BN_clear_free(dhg.g);
BN_clear_free(dhg.p);
continue;
}
break;
}
free(line);
line = NULL;
fclose(f);
if (bestcount != which + 1) {
logit("WARNING: selected prime disappeared in %s, giving up",
_PATH_DH_MODULI);
return (dh_new_group_fallback(max));
}
return (dh_new_group(dhg.g, dhg.p));
}
/* diffie-hellman-groupN-sha1 */
int
dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
{
int i;
int n = BN_num_bits(dh_pub);
int bits_set = 0;
BIGNUM *tmp;
const BIGNUM *dh_p;
DH_get0_pqg(dh, &dh_p, NULL, NULL);
if (BN_is_negative(dh_pub)) {
logit("invalid public DH value: negative");
return 0;
}
if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */
logit("invalid public DH value: <= 1");
return 0;
}
if ((tmp = BN_new()) == NULL) {
error("%s: BN_new failed", __func__);
return 0;
}
if (!BN_sub(tmp, dh_p, BN_value_one()) ||
BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */
BN_clear_free(tmp);
logit("invalid public DH value: >= p-1");
return 0;
}
BN_clear_free(tmp);
for (i = 0; i <= n; i++)
if (BN_is_bit_set(dh_pub, i))
bits_set++;
debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p));
/*
* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial
*/
if (bits_set < 4) {
logit("invalid public DH value (%d/%d)",
bits_set, BN_num_bits(dh_p));
return 0;
}
return 1;
}
int
dh_gen_key(DH *dh, int need)
{
int pbits;
const BIGNUM *dh_p, *pub_key;
DH_get0_pqg(dh, &dh_p, NULL, NULL);
if (need < 0 || dh_p == NULL ||
(pbits = BN_num_bits(dh_p)) <= 0 ||
need > INT_MAX / 2 || 2 * need > pbits)
return SSH_ERR_INVALID_ARGUMENT;
if (need < 256)
need = 256;
/*
* Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
* so double requested need here.
*/
if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
return SSH_ERR_LIBCRYPTO_ERROR;
if (DH_generate_key(dh) == 0)
return SSH_ERR_LIBCRYPTO_ERROR;
DH_get0_key(dh, &pub_key, NULL);
if (!dh_pub_is_valid(dh, pub_key))
return SSH_ERR_INVALID_FORMAT;
return 0;
}
DH *
dh_new_group_asc(const char *gen, const char *modulus)
{
DH *dh;
BIGNUM *dh_p = NULL, *dh_g = NULL;
if ((dh = DH_new()) == NULL)
return NULL;
if (BN_hex2bn(&dh_p, modulus) == 0 ||
BN_hex2bn(&dh_g, gen) == 0)
goto fail;
if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
goto fail;
return dh;
fail:
DH_free(dh);
BN_clear_free(dh_p);
BN_clear_free(dh_g);
return NULL;
}
/*
* This just returns the group, we still need to generate the exchange
* value.
*/
DH *
dh_new_group(BIGNUM *gen, BIGNUM *modulus)
{
DH *dh;
if ((dh = DH_new()) == NULL)
return NULL;
if (!DH_set0_pqg(dh, modulus, NULL, gen)) {
DH_free(dh);
return NULL;
}
return dh;
}
/* rfc2409 "Second Oakley Group" (1024 bits) */
DH *
dh_new_group1(void)
{
static char *gen = "2", *group1 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
"FFFFFFFF" "FFFFFFFF";
return (dh_new_group_asc(gen, group1));
}
/* rfc3526 group 14 "2048-bit MODP Group" */
DH *
dh_new_group14(void)
{
static char *gen = "2", *group14 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
"15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
return (dh_new_group_asc(gen, group14));
}
/* rfc3526 group 16 "4096-bit MODP Group" */
DH *
dh_new_group16(void)
{
static char *gen = "2", *group16 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
"15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
"ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
"ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
"F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
"43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
"88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
"2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
"287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
"1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
"93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199"
"FFFFFFFF" "FFFFFFFF";
return (dh_new_group_asc(gen, group16));
}
/* rfc3526 group 18 "8192-bit MODP Group" */
DH *
dh_new_group18(void)
{
- static char *gen = "2", *group16 =
+ static char *gen = "2", *group18 =
"FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
"29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
"EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
"E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
"EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
"C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
"83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
"670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
"E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
"DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
"15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
"ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
"ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
"F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
"BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
"43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
"88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
"2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
"287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
"1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
"93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34028492"
"36C3FAB4" "D27C7026" "C1D4DCB2" "602646DE" "C9751E76" "3DBA37BD"
"F8FF9406" "AD9E530E" "E5DB382F" "413001AE" "B06A53ED" "9027D831"
"179727B0" "865A8918" "DA3EDBEB" "CF9B14ED" "44CE6CBA" "CED4BB1B"
"DB7F1447" "E6CC254B" "33205151" "2BD7AF42" "6FB8F401" "378CD2BF"
"5983CA01" "C64B92EC" "F032EA15" "D1721D03" "F482D7CE" "6E74FEF6"
"D55E702F" "46980C82" "B5A84031" "900B1C9E" "59E7C97F" "BEC7E8F3"
"23A97A7E" "36CC88BE" "0F1D45B7" "FF585AC5" "4BD407B2" "2B4154AA"
"CC8F6D7E" "BF48E1D8" "14CC5ED2" "0F8037E0" "A79715EE" "F29BE328"
"06A1D58B" "B7C5DA76" "F550AA3D" "8A1FBFF0" "EB19CCB1" "A313D55C"
"DA56C9EC" "2EF29632" "387FE8D7" "6E3C0468" "043E8F66" "3F4860EE"
"12BF2D5B" "0B7474D6" "E694F91E" "6DBE1159" "74A3926F" "12FEE5E4"
"38777CB6" "A932DF8C" "D8BEC4D0" "73B931BA" "3BC832B6" "8D9DD300"
"741FA7BF" "8AFC47ED" "2576F693" "6BA42466" "3AAB639C" "5AE4F568"
"3423B474" "2BF1C978" "238F16CB" "E39D652D" "E3FDB8BE" "FC848AD9"
"22222E04" "A4037C07" "13EB57A8" "1A23F0C7" "3473FC64" "6CEA306B"
"4BCBC886" "2F8385DD" "FA9D4B7F" "A2C087E8" "79683303" "ED5BDD3A"
"062B3CF5" "B3A278A6" "6D2A13F8" "3F44F82D" "DF310EE0" "74AB6A36"
"4597E899" "A0255DC1" "64F31CC5" "0846851D" "F9AB4819" "5DED7EA1"
"B1D510BD" "7EE74D73" "FAF36BC3" "1ECFA268" "359046F4" "EB879F92"
"4009438B" "481C6CD7" "889A002E" "D5EE382B" "C9190DA6" "FC026E47"
"9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71"
"60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF";
- return (dh_new_group_asc(gen, group16));
+ return (dh_new_group_asc(gen, group18));
}
/* Select fallback group used by DH-GEX if moduli file cannot be read. */
DH *
dh_new_group_fallback(int max)
{
debug3("%s: requested max size %d", __func__, max);
if (max < 3072) {
debug3("using 2k bit group 14");
return dh_new_group14();
} else if (max < 6144) {
debug3("using 4k bit group 16");
return dh_new_group16();
}
debug3("using 8k bit group 18");
return dh_new_group18();
}
/*
* Estimates the group order for a Diffie-Hellman group that has an
* attack complexity approximately the same as O(2**bits).
* Values from NIST Special Publication 800-57: Recommendation for Key
* Management Part 1 (rev 3) limited by the recommended maximum value
* from RFC4419 section 3.
*/
u_int
dh_estimate(int bits)
{
if (bits <= 112)
return 2048;
if (bits <= 128)
return 3072;
if (bits <= 192)
return 7680;
return 8192;
}
#endif /* WITH_OPENSSL */
diff --git a/dh.h b/dh.h
index 344b29e356ce..adb643a75343 100644
--- a/dh.h
+++ b/dh.h
@@ -1,80 +1,80 @@
-/* $OpenBSD: dh.h,v 1.15 2016/05/02 10:26:04 djm Exp $ */
+/* $OpenBSD: dh.h,v 1.17 2019/01/20 01:12:40 dtucker Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DH_H
#define DH_H
struct dhgroup {
int size;
BIGNUM *g;
BIGNUM *p;
};
DH *choose_dh(int, int, int);
DH *dh_new_group_asc(const char *, const char *);
DH *dh_new_group(BIGNUM *, BIGNUM *);
DH *dh_new_group1(void);
DH *dh_new_group14(void);
DH *dh_new_group16(void);
DH *dh_new_group18(void);
DH *dh_new_group_fallback(int);
int dh_gen_key(DH *, int);
int dh_pub_is_valid(const DH *, const BIGNUM *);
u_int dh_estimate(int);
/*
* Max value from RFC4419.
- * Miniumum increased in light of DH precomputation attacks.
+ * Min value from RFC8270.
*/
#define DH_GRP_MIN 2048
#define DH_GRP_MAX 8192
/*
* Values for "type" field of moduli(5)
* Specifies the internal structure of the prime modulus.
*/
#define MODULI_TYPE_UNKNOWN (0)
#define MODULI_TYPE_UNSTRUCTURED (1)
#define MODULI_TYPE_SAFE (2)
#define MODULI_TYPE_SCHNORR (3)
#define MODULI_TYPE_SOPHIE_GERMAIN (4)
#define MODULI_TYPE_STRONG (5)
/*
* Values for "tests" field of moduli(5)
* Specifies the methods used in checking for primality.
* Usually, more than one test is used.
*/
#define MODULI_TESTS_UNTESTED (0x00)
#define MODULI_TESTS_COMPOSITE (0x01)
#define MODULI_TESTS_SIEVE (0x02)
#define MODULI_TESTS_MILLER_RABIN (0x04)
#define MODULI_TESTS_JACOBI (0x08)
#define MODULI_TESTS_ELLIPTIC (0x10)
#endif
diff --git a/dispatch.c b/dispatch.c
index 0b3ea614e150..6e4c501e0573 100644
--- a/dispatch.c
+++ b/dispatch.c
@@ -1,135 +1,135 @@
-/* $OpenBSD: dispatch.c,v 1.31 2017/05/31 07:00:13 markus Exp $ */
+/* $OpenBSD: dispatch.c,v 1.32 2019/01/19 21:33:13 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <signal.h>
#include <stdarg.h>
#include "ssh2.h"
#include "log.h"
#include "dispatch.h"
#include "packet.h"
#include "compat.h"
#include "ssherr.h"
int
dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
int r;
logit("dispatch_protocol_error: type %d seq %u", type, seq);
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
return 0;
}
int
dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh)
{
logit("dispatch_protocol_ignore: type %d seq %u", type, seq);
return 0;
}
void
ssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt)
{
u_int i;
for (i = 0; i < DISPATCH_MAX; i++)
ssh->dispatch[i] = dflt;
}
void
ssh_dispatch_range(struct ssh *ssh, u_int from, u_int to, dispatch_fn *fn)
{
u_int i;
for (i = from; i <= to; i++) {
if (i >= DISPATCH_MAX)
break;
ssh->dispatch[i] = fn;
}
}
void
ssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn)
{
ssh->dispatch[type] = fn;
}
int
ssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done)
{
int r;
u_char type;
u_int32_t seqnr;
for (;;) {
if (mode == DISPATCH_BLOCK) {
r = ssh_packet_read_seqnr(ssh, &type, &seqnr);
if (r != 0)
return r;
} else {
r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr);
if (r != 0)
return r;
if (type == SSH_MSG_NONE)
return 0;
}
if (type > 0 && type < DISPATCH_MAX &&
ssh->dispatch[type] != NULL) {
if (ssh->dispatch_skip_packets) {
debug2("skipped packet (type %u)", type);
ssh->dispatch_skip_packets--;
continue;
}
r = (*ssh->dispatch[type])(type, seqnr, ssh);
if (r != 0)
return r;
} else {
r = sshpkt_disconnect(ssh,
"protocol error: rcvd type %d", type);
if (r != 0)
return r;
return SSH_ERR_DISCONNECTED;
}
if (done != NULL && *done)
return 0;
}
}
void
ssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done)
{
int r;
if ((r = ssh_dispatch_run(ssh, mode, done)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
}
diff --git a/dispatch.h b/dispatch.h
index 17a6f3db6338..a22d7749febb 100644
--- a/dispatch.h
+++ b/dispatch.h
@@ -1,56 +1,49 @@
-/* $OpenBSD: dispatch.h,v 1.14 2017/05/31 07:00:13 markus Exp $ */
+/* $OpenBSD: dispatch.h,v 1.15 2019/01/19 21:45:31 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DISPATCH_H
#define DISPATCH_H
#define DISPATCH_MAX 255
enum {
DISPATCH_BLOCK,
DISPATCH_NONBLOCK
};
struct ssh;
typedef int dispatch_fn(int, u_int32_t, struct ssh *);
int dispatch_protocol_error(int, u_int32_t, struct ssh *);
int dispatch_protocol_ignore(int, u_int32_t, struct ssh *);
void ssh_dispatch_init(struct ssh *, dispatch_fn *);
void ssh_dispatch_set(struct ssh *, int, dispatch_fn *);
void ssh_dispatch_range(struct ssh *, u_int, u_int, dispatch_fn *);
int ssh_dispatch_run(struct ssh *, int, volatile sig_atomic_t *);
void ssh_dispatch_run_fatal(struct ssh *, int, volatile sig_atomic_t *);
-#define dispatch_init(dflt) \
- ssh_dispatch_init(active_state, (dflt))
-#define dispatch_range(from, to, fn) \
- ssh_dispatch_range(active_state, (from), (to), (fn))
-#define dispatch_set(type, fn) \
- ssh_dispatch_set(active_state, (type), (fn))
-
#endif
diff --git a/entropy.c b/entropy.c
index c178c00cf61c..31a7f1c3ef54 100644
--- a/entropy.c
+++ b/entropy.c
@@ -1,250 +1,261 @@
/*
* Copyright (c) 2001 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
+#define RANDOM_SEED_SIZE 48
+
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <stddef.h> /* for offsetof */
#include <openssl/rand.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include "openbsd-compat/openssl-compat.h"
#include "ssh.h"
#include "misc.h"
#include "xmalloc.h"
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
#include "sshbuf.h"
#include "ssherr.h"
/*
* Portable OpenSSH PRNG seeding:
* If OpenSSL has not "internally seeded" itself (e.g. pulled data from
* /dev/random), then collect RANDOM_SEED_SIZE bytes of randomness from
* PRNGd.
*/
#ifndef OPENSSL_PRNG_ONLY
-#define RANDOM_SEED_SIZE 48
-
/*
* Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
* listening either on 'tcp_port', or via Unix domain socket at *
* 'socket_path'.
* Either a non-zero tcp_port or a non-null socket_path must be
* supplied.
* Returns 0 on success, -1 on error
*/
int
get_random_bytes_prngd(unsigned char *buf, int len,
unsigned short tcp_port, char *socket_path)
{
int fd, addr_len, rval, errors;
u_char msg[2];
struct sockaddr_storage addr;
struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
mysig_t old_sigpipe;
/* Sanity checks */
if (socket_path == NULL && tcp_port == 0)
fatal("You must specify a port or a socket");
if (socket_path != NULL &&
strlen(socket_path) >= sizeof(addr_un->sun_path))
fatal("Random pool path is too long");
if (len <= 0 || len > 255)
fatal("Too many bytes (%d) to read from PRNGD", len);
memset(&addr, '\0', sizeof(addr));
if (tcp_port != 0) {
addr_in->sin_family = AF_INET;
addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr_in->sin_port = htons(tcp_port);
addr_len = sizeof(*addr_in);
} else {
addr_un->sun_family = AF_UNIX;
strlcpy(addr_un->sun_path, socket_path,
sizeof(addr_un->sun_path));
addr_len = offsetof(struct sockaddr_un, sun_path) +
strlen(socket_path) + 1;
}
old_sigpipe = signal(SIGPIPE, SIG_IGN);
errors = 0;
rval = -1;
reopen:
fd = socket(addr.ss_family, SOCK_STREAM, 0);
if (fd == -1) {
error("Couldn't create socket: %s", strerror(errno));
goto done;
}
if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) {
if (tcp_port != 0) {
error("Couldn't connect to PRNGD port %d: %s",
tcp_port, strerror(errno));
} else {
error("Couldn't connect to PRNGD socket \"%s\": %s",
addr_un->sun_path, strerror(errno));
}
goto done;
}
/* Send blocking read request to PRNGD */
msg[0] = 0x02;
msg[1] = len;
if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) {
if (errno == EPIPE && errors < 10) {
close(fd);
errors++;
goto reopen;
}
error("Couldn't write to PRNGD socket: %s",
strerror(errno));
goto done;
}
if (atomicio(read, fd, buf, len) != (size_t)len) {
if (errno == EPIPE && errors < 10) {
close(fd);
errors++;
goto reopen;
}
error("Couldn't read from PRNGD socket: %s",
strerror(errno));
goto done;
}
rval = 0;
done:
signal(SIGPIPE, old_sigpipe);
if (fd != -1)
close(fd);
return rval;
}
static int
seed_from_prngd(unsigned char *buf, size_t bytes)
{
#ifdef PRNGD_PORT
debug("trying egd/prngd port %d", PRNGD_PORT);
if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0)
return 0;
#endif
#ifdef PRNGD_SOCKET
debug("trying egd/prngd socket %s", PRNGD_SOCKET);
if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0)
return 0;
#endif
return -1;
}
void
rexec_send_rng_seed(struct sshbuf *m)
{
u_char buf[RANDOM_SEED_SIZE];
size_t len = sizeof(buf);
int r;
if (RAND_bytes(buf, sizeof(buf)) <= 0) {
error("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
len = 0;
}
if ((r = sshbuf_put_string(m, buf, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
explicit_bzero(buf, sizeof(buf));
}
void
rexec_recv_rng_seed(struct sshbuf *m)
{
u_char *buf = NULL;
size_t len = 0;
int r;
if ((r = sshbuf_get_string_direct(m, &buf, &len)) != 0
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("rexec_recv_rng_seed: seeding rng with %u bytes", len);
RAND_add(buf, len, len);
}
#endif /* OPENSSL_PRNG_ONLY */
void
seed_rng(void)
{
-#ifndef OPENSSL_PRNG_ONLY
unsigned char buf[RANDOM_SEED_SIZE];
-#endif
- if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay()))
+
+ /* Initialise libcrypto */
+ ssh_libcrypto_init();
+
+ if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER,
+ OpenSSL_version_num()))
fatal("OpenSSL version mismatch. Built against %lx, you "
- "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
+ "have %lx", (u_long)OPENSSL_VERSION_NUMBER,
+ OpenSSL_version_num());
#ifndef OPENSSL_PRNG_ONLY
- if (RAND_status() == 1) {
+ if (RAND_status() == 1)
debug3("RNG is ready, skipping seeding");
- return;
+ else {
+ if (seed_from_prngd(buf, sizeof(buf)) == -1)
+ fatal("Could not obtain seed from PRNGd");
+ RAND_add(buf, sizeof(buf), sizeof(buf));
}
-
- if (seed_from_prngd(buf, sizeof(buf)) == -1)
- fatal("Could not obtain seed from PRNGd");
- RAND_add(buf, sizeof(buf), sizeof(buf));
- memset(buf, '\0', sizeof(buf));
-
#endif /* OPENSSL_PRNG_ONLY */
+
if (RAND_status() != 1)
fatal("PRNG is not seeded");
+
+ /* Ensure arc4random() is primed */
+ arc4random_buf(buf, sizeof(buf));
+ explicit_bzero(buf, sizeof(buf));
}
#else /* WITH_OPENSSL */
-/* Handled in arc4random() */
+/* Acutal initialisation is handled in arc4random() */
void
seed_rng(void)
{
+ unsigned char buf[RANDOM_SEED_SIZE];
+
+ /* Ensure arc4random() is primed */
+ arc4random_buf(buf, sizeof(buf));
+ explicit_bzero(buf, sizeof(buf));
}
#endif /* WITH_OPENSSL */
diff --git a/groupaccess.c b/groupaccess.c
index 9e4d25521647..80d3019152c2 100644
--- a/groupaccess.c
+++ b/groupaccess.c
@@ -1,133 +1,134 @@
-/* $OpenBSD: groupaccess.c,v 1.16 2015/05/04 06:10:48 djm Exp $ */
+/* $OpenBSD: groupaccess.c,v 1.17 2019/03/06 22:14:23 dtucker Exp $ */
/*
* Copyright (c) 2001 Kevin Steves. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <grp.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "xmalloc.h"
#include "groupaccess.h"
#include "match.h"
#include "log.h"
static int ngroups;
static char **groups_byname;
/*
* Initialize group access list for user with primary (base) and
* supplementary groups. Return the number of groups in the list.
*/
int
ga_init(const char *user, gid_t base)
{
gid_t *groups_bygid;
int i, j, retry = 0;
struct group *gr;
if (ngroups > 0)
ga_free();
ngroups = NGROUPS_MAX;
#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX));
#endif
groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid));
while (getgrouplist(user, base, groups_bygid, &ngroups) == -1) {
if (retry++ > 0)
fatal("getgrouplist: groups list too small");
groups_bygid = xreallocarray(groups_bygid, ngroups,
sizeof(*groups_bygid));
}
groups_byname = xcalloc(ngroups, sizeof(*groups_byname));
for (i = 0, j = 0; i < ngroups; i++)
if ((gr = getgrgid(groups_bygid[i])) != NULL)
groups_byname[j++] = xstrdup(gr->gr_name);
free(groups_bygid);
return (ngroups = j);
}
/*
* Return 1 if one of user's groups is contained in groups.
* Return 0 otherwise. Use match_pattern() for string comparison.
*/
int
ga_match(char * const *groups, int n)
{
int i, j;
for (i = 0; i < ngroups; i++)
for (j = 0; j < n; j++)
if (match_pattern(groups_byname[i], groups[j]))
return 1;
return 0;
}
/*
* Return 1 if one of user's groups matches group_pattern list.
* Return 0 on negated or no match.
*/
int
ga_match_pattern_list(const char *group_pattern)
{
int i, found = 0;
for (i = 0; i < ngroups; i++) {
- switch (match_pattern_list(groups_byname[i], group_pattern, 0)) {
+ switch (match_usergroup_pattern_list(groups_byname[i],
+ group_pattern)) {
case -1:
return 0; /* Negated match wins */
case 0:
continue;
case 1:
found = 1;
}
}
return found;
}
/*
* Free memory allocated for group access list.
*/
void
ga_free(void)
{
int i;
if (ngroups > 0) {
for (i = 0; i < ngroups; i++)
free(groups_byname[i]);
ngroups = 0;
free(groups_byname);
groups_byname = NULL;
}
}
diff --git a/kex.c b/kex.c
index 25f9f66f69af..34808b5c39da 100644
--- a/kex.c
+++ b/kex.c
@@ -1,1043 +1,1313 @@
-/* $OpenBSD: kex.c,v 1.141 2018/07/09 13:37:10 sf Exp $ */
+/* $OpenBSD: kex.c,v 1.150 2019/01/21 12:08:13 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
-
+#include <sys/types.h>
+#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <poll.h>
#ifdef WITH_OPENSSL
#include <openssl/crypto.h>
#include <openssl/dh.h>
#endif
+#include "ssh.h"
#include "ssh2.h"
+#include "atomicio.h"
+#include "version.h"
#include "packet.h"
#include "compat.h"
#include "cipher.h"
#include "sshkey.h"
#include "kex.h"
#include "log.h"
#include "mac.h"
#include "match.h"
#include "misc.h"
#include "dispatch.h"
#include "monitor.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "digest.h"
/* prototype */
static int kex_choose_conf(struct ssh *);
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
static const char *proposal_names[PROPOSAL_MAX] = {
"KEX algorithms",
"host key algorithms",
"ciphers ctos",
"ciphers stoc",
"MACs ctos",
"MACs stoc",
"compression ctos",
"compression stoc",
"languages ctos",
"languages stoc",
};
struct kexalg {
char *name;
u_int type;
int ec_nid;
int hash_alg;
};
static const struct kexalg kexalgs[] = {
#ifdef WITH_OPENSSL
{ KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
{ KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
{ KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
{ KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
{ KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
{ KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
#ifdef HAVE_EVP_SHA256
{ KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
#endif /* HAVE_EVP_SHA256 */
#ifdef OPENSSL_HAS_ECC
{ KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
{ KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1,
SSH_DIGEST_SHA384 },
# ifdef OPENSSL_HAS_NISTP521
{ KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
SSH_DIGEST_SHA512 },
# endif /* OPENSSL_HAS_NISTP521 */
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL)
{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
{ KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
+ { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0,
+ SSH_DIGEST_SHA512 },
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
{ NULL, -1, -1, -1},
};
char *
kex_alg_list(char sep)
{
char *ret = NULL, *tmp;
size_t nlen, rlen = 0;
const struct kexalg *k;
for (k = kexalgs; k->name != NULL; k++) {
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(k->name);
if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
free(ret);
return NULL;
}
ret = tmp;
memcpy(ret + rlen, k->name, nlen + 1);
rlen += nlen;
}
return ret;
}
static const struct kexalg *
kex_alg_by_name(const char *name)
{
const struct kexalg *k;
for (k = kexalgs; k->name != NULL; k++) {
if (strcmp(k->name, name) == 0)
return k;
}
return NULL;
}
/* Validate KEX method name list */
int
kex_names_valid(const char *names)
{
char *s, *cp, *p;
if (names == NULL || strcmp(names, "") == 0)
return 0;
if ((s = cp = strdup(names)) == NULL)
return 0;
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
if (kex_alg_by_name(p) == NULL) {
error("Unsupported KEX algorithm \"%.100s\"", p);
free(s);
return 0;
}
}
debug3("kex names ok: [%s]", names);
free(s);
return 1;
}
/*
* Concatenate algorithm names, avoiding duplicates in the process.
* Caller must free returned string.
*/
char *
kex_names_cat(const char *a, const char *b)
{
char *ret = NULL, *tmp = NULL, *cp, *p, *m;
size_t len;
if (a == NULL || *a == '\0')
return strdup(b);
if (b == NULL || *b == '\0')
return strdup(a);
if (strlen(b) > 1024*1024)
return NULL;
len = strlen(a) + strlen(b) + 2;
if ((tmp = cp = strdup(b)) == NULL ||
(ret = calloc(1, len)) == NULL) {
free(tmp);
return NULL;
}
strlcpy(ret, a, len);
for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
if ((m = match_list(ret, p, NULL)) != NULL) {
free(m);
continue; /* Algorithm already present */
}
if (strlcat(ret, ",", len) >= len ||
strlcat(ret, p, len) >= len) {
free(tmp);
free(ret);
return NULL; /* Shouldn't happen */
}
}
free(tmp);
return ret;
}
/*
* Assemble a list of algorithms from a default list and a string from a
* configuration file. The user-provided string may begin with '+' to
* indicate that it should be appended to the default or '-' that the
* specified names should be removed.
*/
int
kex_assemble_names(char **listp, const char *def, const char *all)
{
char *cp, *tmp, *patterns;
char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL;
int r = SSH_ERR_INTERNAL_ERROR;
if (listp == NULL || *listp == NULL || **listp == '\0') {
if ((*listp = strdup(def)) == NULL)
return SSH_ERR_ALLOC_FAIL;
return 0;
}
list = *listp;
*listp = NULL;
if (*list == '+') {
/* Append names to default list */
if ((tmp = kex_names_cat(def, list + 1)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
free(list);
list = tmp;
} else if (*list == '-') {
/* Remove names from default list */
if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
free(list);
/* filtering has already been done */
return 0;
} else {
/* Explicit list, overrides default - just use "list" as is */
}
/*
* The supplied names may be a pattern-list. For the -list case,
* the patterns are applied above. For the +list and explicit list
* cases we need to do it now.
*/
ret = NULL;
if ((patterns = opatterns = strdup(list)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
/* Apply positive (i.e. non-negated) patterns from the list */
while ((cp = strsep(&patterns, ",")) != NULL) {
if (*cp == '!') {
/* negated matches are not supported here */
r = SSH_ERR_INVALID_ARGUMENT;
goto fail;
}
free(matching);
if ((matching = match_filter_whitelist(all, cp)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
if ((tmp = kex_names_cat(ret, matching)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
free(ret);
ret = tmp;
}
if (ret == NULL || *ret == '\0') {
/* An empty name-list is an error */
/* XXX better error code? */
r = SSH_ERR_INVALID_ARGUMENT;
goto fail;
}
/* success */
*listp = ret;
ret = NULL;
r = 0;
fail:
free(matching);
free(opatterns);
free(list);
free(ret);
return r;
}
/* put algorithm proposal into buffer */
int
kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
{
u_int i;
int r;
sshbuf_reset(b);
/*
* add a dummy cookie, the cookie will be overwritten by
* kex_send_kexinit(), each time a kexinit is set
*/
for (i = 0; i < KEX_COOKIE_LEN; i++) {
if ((r = sshbuf_put_u8(b, 0)) != 0)
return r;
}
for (i = 0; i < PROPOSAL_MAX; i++) {
if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
return r;
}
if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
(r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */
return r;
return 0;
}
/* parse buffer and return algorithm proposal */
int
kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
{
struct sshbuf *b = NULL;
u_char v;
u_int i;
char **proposal = NULL;
int r;
*propp = NULL;
if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((b = sshbuf_fromb(raw)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */
goto out;
/* extract kex init proposal strings */
for (i = 0; i < PROPOSAL_MAX; i++) {
if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
goto out;
debug2("%s: %s", proposal_names[i], proposal[i]);
}
/* first kex follows / reserved */
if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
(r = sshbuf_get_u32(b, &i)) != 0) /* reserved */
goto out;
if (first_kex_follows != NULL)
*first_kex_follows = v;
debug2("first_kex_follows %d ", v);
debug2("reserved %u ", i);
r = 0;
*propp = proposal;
out:
if (r != 0 && proposal != NULL)
kex_prop_free(proposal);
sshbuf_free(b);
return r;
}
void
kex_prop_free(char **proposal)
{
u_int i;
if (proposal == NULL)
return;
for (i = 0; i < PROPOSAL_MAX; i++)
free(proposal[i]);
free(proposal);
}
/* ARGSUSED */
static int
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
int r;
error("kex protocol error: type %d seq %u", type, seq);
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
return 0;
}
static void
kex_reset_dispatch(struct ssh *ssh)
{
ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
}
static int
kex_send_ext_info(struct ssh *ssh)
{
int r;
char *algs;
if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
return SSH_ERR_ALLOC_FAIL;
/* XXX filter algs list by allowed pubkey/hostbased types */
if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
(r = sshpkt_put_u32(ssh, 1)) != 0 ||
(r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
(r = sshpkt_put_cstring(ssh, algs)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
/* success */
r = 0;
out:
free(algs);
return r;
}
int
kex_send_newkeys(struct ssh *ssh)
{
int r;
kex_reset_dispatch(ssh);
if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
debug("SSH2_MSG_NEWKEYS sent");
debug("expecting SSH2_MSG_NEWKEYS");
ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
if (ssh->kex->ext_info_c)
if ((r = kex_send_ext_info(ssh)) != 0)
return r;
return 0;
}
int
kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
u_int32_t i, ninfo;
char *name;
u_char *val;
size_t vlen;
int r;
debug("SSH2_MSG_EXT_INFO received");
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
return r;
for (i = 0; i < ninfo; i++) {
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
return r;
if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
free(name);
return r;
}
if (strcmp(name, "server-sig-algs") == 0) {
/* Ensure no \0 lurking in value */
if (memchr(val, '\0', vlen) != NULL) {
error("%s: nul byte in %s", __func__, name);
return SSH_ERR_INVALID_FORMAT;
}
debug("%s: %s=<%s>", __func__, name, val);
kex->server_sig_algs = val;
val = NULL;
} else
debug("%s: %s (unrecognised)", __func__, name);
free(name);
free(val);
}
return sshpkt_get_end(ssh);
}
static int
kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
int r;
debug("SSH2_MSG_NEWKEYS received");
ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
if ((r = sshpkt_get_end(ssh)) != 0)
return r;
if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
return r;
kex->done = 1;
+ kex->flags &= ~KEX_INITIAL;
sshbuf_reset(kex->peer);
/* sshbuf_reset(kex->my); */
kex->flags &= ~KEX_INIT_SENT;
free(kex->name);
kex->name = NULL;
return 0;
}
int
kex_send_kexinit(struct ssh *ssh)
{
u_char *cookie;
struct kex *kex = ssh->kex;
int r;
if (kex == NULL)
return SSH_ERR_INTERNAL_ERROR;
if (kex->flags & KEX_INIT_SENT)
return 0;
kex->done = 0;
/* generate a random cookie */
if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
return SSH_ERR_INVALID_FORMAT;
if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL)
return SSH_ERR_INTERNAL_ERROR;
arc4random_buf(cookie, KEX_COOKIE_LEN);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
(r = sshpkt_putb(ssh, kex->my)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
debug("SSH2_MSG_KEXINIT sent");
kex->flags |= KEX_INIT_SENT;
return 0;
}
/* ARGSUSED */
int
kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
const u_char *ptr;
u_int i;
size_t dlen;
int r;
debug("SSH2_MSG_KEXINIT received");
if (kex == NULL)
return SSH_ERR_INVALID_ARGUMENT;
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
ptr = sshpkt_ptr(ssh, &dlen);
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
return r;
/* discard packet */
for (i = 0; i < KEX_COOKIE_LEN; i++)
if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
return r;
for (i = 0; i < PROPOSAL_MAX; i++)
if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
return r;
/*
* XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
* KEX method has the server move first, but a server might be using
* a custom method or one that we otherwise don't support. We should
* be prepared to remember first_kex_follows here so we can eat a
* packet later.
* XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
* for cases where the server *doesn't* go first. I guess we should
* ignore it when it is set for these cases, which is what we do now.
*/
if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
(r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
(r = sshpkt_get_end(ssh)) != 0)
return r;
if (!(kex->flags & KEX_INIT_SENT))
if ((r = kex_send_kexinit(ssh)) != 0)
return r;
if ((r = kex_choose_conf(ssh)) != 0)
return r;
if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
return (kex->kex[kex->kex_type])(ssh);
return SSH_ERR_INTERNAL_ERROR;
}
-int
-kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
+struct kex *
+kex_new(void)
{
struct kex *kex;
- int r;
- *kexp = NULL;
- if ((kex = calloc(1, sizeof(*kex))) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((kex->peer = sshbuf_new()) == NULL ||
- (kex->my = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = kex_prop2buf(kex->my, proposal)) != 0)
- goto out;
- kex->done = 0;
- kex_reset_dispatch(ssh);
- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
- r = 0;
- *kexp = kex;
- out:
- if (r != 0)
+ if ((kex = calloc(1, sizeof(*kex))) == NULL ||
+ (kex->peer = sshbuf_new()) == NULL ||
+ (kex->my = sshbuf_new()) == NULL ||
+ (kex->client_version = sshbuf_new()) == NULL ||
+ (kex->server_version = sshbuf_new()) == NULL) {
kex_free(kex);
- return r;
+ return NULL;
+ }
+ return kex;
}
void
kex_free_newkeys(struct newkeys *newkeys)
{
if (newkeys == NULL)
return;
if (newkeys->enc.key) {
explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
free(newkeys->enc.key);
newkeys->enc.key = NULL;
}
if (newkeys->enc.iv) {
explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
free(newkeys->enc.iv);
newkeys->enc.iv = NULL;
}
free(newkeys->enc.name);
explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
free(newkeys->comp.name);
explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
mac_clear(&newkeys->mac);
if (newkeys->mac.key) {
explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
free(newkeys->mac.key);
newkeys->mac.key = NULL;
}
free(newkeys->mac.name);
explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
explicit_bzero(newkeys, sizeof(*newkeys));
free(newkeys);
}
void
kex_free(struct kex *kex)
{
u_int mode;
+ if (kex == NULL)
+ return;
+
#ifdef WITH_OPENSSL
DH_free(kex->dh);
#ifdef OPENSSL_HAS_ECC
EC_KEY_free(kex->ec_client_key);
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
for (mode = 0; mode < MODE_MAX; mode++) {
kex_free_newkeys(kex->newkeys[mode]);
kex->newkeys[mode] = NULL;
}
sshbuf_free(kex->peer);
sshbuf_free(kex->my);
+ sshbuf_free(kex->client_version);
+ sshbuf_free(kex->server_version);
+ sshbuf_free(kex->client_pub);
free(kex->session_id);
- free(kex->client_version_string);
- free(kex->server_version_string);
free(kex->failed_choice);
free(kex->hostkey_alg);
free(kex->name);
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
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
{
int r;
- if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
+ if ((r = kex_ready(ssh, proposal)) != 0)
return r;
if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
kex_free(ssh->kex);
ssh->kex = NULL;
return r;
}
return 0;
}
/*
* Request key re-exchange, returns 0 on success or a ssherr.h error
* code otherwise. Must not be called if KEX is incomplete or in-progress.
*/
int
kex_start_rekex(struct ssh *ssh)
{
if (ssh->kex == NULL) {
error("%s: no kex", __func__);
return SSH_ERR_INTERNAL_ERROR;
}
if (ssh->kex->done == 0) {
error("%s: requested twice", __func__);
return SSH_ERR_INTERNAL_ERROR;
}
ssh->kex->done = 0;
return kex_send_kexinit(ssh);
}
static int
choose_enc(struct sshenc *enc, char *client, char *server)
{
char *name = match_list(client, server, NULL);
if (name == NULL)
return SSH_ERR_NO_CIPHER_ALG_MATCH;
if ((enc->cipher = cipher_by_name(name)) == NULL) {
free(name);
return SSH_ERR_INTERNAL_ERROR;
}
enc->name = name;
enc->enabled = 0;
enc->iv = NULL;
enc->iv_len = cipher_ivlen(enc->cipher);
enc->key = NULL;
enc->key_len = cipher_keylen(enc->cipher);
enc->block_size = cipher_blocksize(enc->cipher);
return 0;
}
static int
choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
{
char *name = match_list(client, server, NULL);
if (name == NULL)
return SSH_ERR_NO_MAC_ALG_MATCH;
if (mac_setup(mac, name) < 0) {
free(name);
return SSH_ERR_INTERNAL_ERROR;
}
mac->name = name;
mac->key = NULL;
mac->enabled = 0;
return 0;
}
static int
choose_comp(struct sshcomp *comp, char *client, char *server)
{
char *name = match_list(client, server, NULL);
if (name == NULL)
return SSH_ERR_NO_COMPRESS_ALG_MATCH;
if (strcmp(name, "zlib@openssh.com") == 0) {
comp->type = COMP_DELAYED;
} else if (strcmp(name, "zlib") == 0) {
comp->type = COMP_ZLIB;
} else if (strcmp(name, "none") == 0) {
comp->type = COMP_NONE;
} else {
free(name);
return SSH_ERR_INTERNAL_ERROR;
}
comp->name = name;
return 0;
}
static int
choose_kex(struct kex *k, char *client, char *server)
{
const struct kexalg *kexalg;
k->name = match_list(client, server, NULL);
debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
if (k->name == NULL)
return SSH_ERR_NO_KEX_ALG_MATCH;
if ((kexalg = kex_alg_by_name(k->name)) == NULL)
return SSH_ERR_INTERNAL_ERROR;
k->kex_type = kexalg->type;
k->hash_alg = kexalg->hash_alg;
k->ec_nid = kexalg->ec_nid;
return 0;
}
static int
choose_hostkeyalg(struct kex *k, char *client, char *server)
{
k->hostkey_alg = match_list(client, server, NULL);
debug("kex: host key algorithm: %s",
k->hostkey_alg ? k->hostkey_alg : "(no match)");
if (k->hostkey_alg == NULL)
return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
if (k->hostkey_type == KEY_UNSPEC)
return SSH_ERR_INTERNAL_ERROR;
k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
return 0;
}
static int
proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
{
static int check[] = {
PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
};
int *idx;
char *p;
for (idx = &check[0]; *idx != -1; idx++) {
if ((p = strchr(my[*idx], ',')) != NULL)
*p = '\0';
if ((p = strchr(peer[*idx], ',')) != NULL)
*p = '\0';
if (strcmp(my[*idx], peer[*idx]) != 0) {
debug2("proposal mismatch: my %s peer %s",
my[*idx], peer[*idx]);
return (0);
}
}
debug2("proposals match");
return (1);
}
static int
kex_choose_conf(struct ssh *ssh)
{
struct kex *kex = ssh->kex;
struct newkeys *newkeys;
char **my = NULL, **peer = NULL;
char **cprop, **sprop;
int nenc, nmac, ncomp;
u_int mode, ctos, need, dh_need, authlen;
int r, first_kex_follows;
debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
goto out;
debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
goto out;
if (kex->server) {
cprop=peer;
sprop=my;
} else {
cprop=my;
sprop=peer;
}
/* Check whether client supports ext_info_c */
- if (kex->server) {
+ if (kex->server && (kex->flags & KEX_INITIAL)) {
char *ext;
ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
kex->ext_info_c = (ext != NULL);
free(ext);
}
/* Algorithm Negotiation */
if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
sprop[PROPOSAL_KEX_ALGS])) != 0) {
kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
peer[PROPOSAL_KEX_ALGS] = NULL;
goto out;
}
if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
goto out;
}
for (mode = 0; mode < MODE_MAX; mode++) {
if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
kex->newkeys[mode] = newkeys;
ctos = (!kex->server && mode == MODE_OUT) ||
(kex->server && mode == MODE_IN);
nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
if ((r = choose_enc(&newkeys->enc, cprop[nenc],
sprop[nenc])) != 0) {
kex->failed_choice = peer[nenc];
peer[nenc] = NULL;
goto out;
}
authlen = cipher_authlen(newkeys->enc.cipher);
/* ignore mac for authenticated encryption */
if (authlen == 0 &&
(r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
sprop[nmac])) != 0) {
kex->failed_choice = peer[nmac];
peer[nmac] = NULL;
goto out;
}
if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
sprop[ncomp])) != 0) {
kex->failed_choice = peer[ncomp];
peer[ncomp] = NULL;
goto out;
}
debug("kex: %s cipher: %s MAC: %s compression: %s",
ctos ? "client->server" : "server->client",
newkeys->enc.name,
authlen == 0 ? newkeys->mac.name : "<implicit>",
newkeys->comp.name);
}
need = dh_need = 0;
for (mode = 0; mode < MODE_MAX; mode++) {
newkeys = kex->newkeys[mode];
need = MAXIMUM(need, newkeys->enc.key_len);
need = MAXIMUM(need, newkeys->enc.block_size);
need = MAXIMUM(need, newkeys->enc.iv_len);
need = MAXIMUM(need, newkeys->mac.key_len);
dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
}
/* XXX need runden? */
kex->we_need = need;
kex->dh_need = dh_need;
/* ignore the next message if the proposals do not match */
if (first_kex_follows && !proposals_match(my, peer))
ssh->dispatch_skip_packets = 1;
r = 0;
out:
kex_prop_free(my);
kex_prop_free(peer);
return r;
}
static int
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
const struct sshbuf *shared_secret, u_char **keyp)
{
struct kex *kex = ssh->kex;
struct ssh_digest_ctx *hashctx = NULL;
char c = id;
u_int have;
size_t mdsz;
u_char *digest;
int r;
if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* K1 = HASH(K || H || "A" || session_id) */
if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
ssh_digest_update(hashctx, hash, hashlen) != 0 ||
ssh_digest_update(hashctx, &c, 1) != 0 ||
ssh_digest_update(hashctx, kex->session_id,
kex->session_id_len) != 0 ||
ssh_digest_final(hashctx, digest, mdsz) != 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
ssh_digest_free(hashctx);
hashctx = NULL;
/*
* expand key:
* Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
* Key = K1 || K2 || ... || Kn
*/
for (have = mdsz; need > have; have += mdsz) {
if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
ssh_digest_update(hashctx, hash, hashlen) != 0 ||
ssh_digest_update(hashctx, digest, have) != 0 ||
ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
ssh_digest_free(hashctx);
hashctx = NULL;
}
#ifdef DEBUG_KEX
fprintf(stderr, "key '%c'== ", c);
dump_digest("key", digest, need);
#endif
*keyp = digest;
digest = NULL;
r = 0;
out:
free(digest);
ssh_digest_free(hashctx);
return r;
}
#define NKEYS 6
int
kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
const struct sshbuf *shared_secret)
{
struct kex *kex = ssh->kex;
u_char *keys[NKEYS];
u_int i, j, mode, ctos;
int r;
+ /* save initial hash as session id */
+ if (kex->session_id == NULL) {
+ kex->session_id_len = hashlen;
+ kex->session_id = malloc(kex->session_id_len);
+ if (kex->session_id == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ memcpy(kex->session_id, hash, kex->session_id_len);
+ }
for (i = 0; i < NKEYS; i++) {
if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
shared_secret, &keys[i])) != 0) {
for (j = 0; j < i; j++)
free(keys[j]);
return r;
}
}
for (mode = 0; mode < MODE_MAX; mode++) {
ctos = (!kex->server && mode == MODE_OUT) ||
(kex->server && mode == MODE_IN);
kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1];
kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
}
return 0;
}
-#ifdef WITH_OPENSSL
int
-kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
- const BIGNUM *secret)
+kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
{
- struct sshbuf *shared_secret;
- int r;
+ struct kex *kex = ssh->kex;
- if ((shared_secret = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0)
- r = kex_derive_keys(ssh, hash, hashlen, shared_secret);
- sshbuf_free(shared_secret);
- return r;
+ *pubp = NULL;
+ *prvp = NULL;
+ if (kex->load_host_public_key == NULL ||
+ kex->load_host_private_key == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ *pubp = kex->load_host_public_key(kex->hostkey_type,
+ kex->hostkey_nid, ssh);
+ *prvp = kex->load_host_private_key(kex->hostkey_type,
+ kex->hostkey_nid, ssh);
+ if (*pubp == NULL)
+ return SSH_ERR_NO_HOSTKEY_LOADED;
+ return 0;
}
-#endif
+int
+kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
+{
+ struct kex *kex = ssh->kex;
+
+ if (kex->verify_host_key == NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ if (server_host_key->type != kex->hostkey_type ||
+ (kex->hostkey_type == KEY_ECDSA &&
+ server_host_key->ecdsa_nid != kex->hostkey_nid))
+ return SSH_ERR_KEY_TYPE_MISMATCH;
+ if (kex->verify_host_key(server_host_key, ssh) == -1)
+ return SSH_ERR_SIGNATURE_INVALID;
+ return 0;
+}
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
void
-dump_digest(char *msg, u_char *digest, int len)
+dump_digest(const char *msg, const u_char *digest, int len)
{
fprintf(stderr, "%s\n", msg);
sshbuf_dump_data(digest, len, stderr);
}
#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;
+}
+
diff --git a/kex.h b/kex.h
index 593de120836e..6d446d1ccbb5 100644
--- a/kex.h
+++ b/kex.h
@@ -1,239 +1,260 @@
-/* $OpenBSD: kex.h,v 1.91 2018/07/11 18:53:29 markus Exp $ */
+/* $OpenBSD: kex.h,v 1.107 2019/01/23 00:30:41 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef KEX_H
#define KEX_H
#include "mac.h"
+#include "crypto_api.h"
#ifdef WITH_LEAKMALLOC
#include "leakmalloc.h"
#endif
#ifdef WITH_OPENSSL
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# else /* OPENSSL_HAS_ECC */
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
#else /* WITH_OPENSSL */
# define DH void
# define BIGNUM void
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
#endif /* WITH_OPENSSL */
#define KEX_COOKIE_LEN 16
#define KEX_DH1 "diffie-hellman-group1-sha1"
#define KEX_DH14_SHA1 "diffie-hellman-group14-sha1"
#define KEX_DH14_SHA256 "diffie-hellman-group14-sha256"
#define KEX_DH16_SHA512 "diffie-hellman-group16-sha512"
#define KEX_DH18_SHA512 "diffie-hellman-group18-sha512"
#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
#define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256"
#define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384"
#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521"
#define KEX_CURVE25519_SHA256 "curve25519-sha256"
#define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org"
+#define KEX_SNTRUP4591761X25519_SHA512 "sntrup4591761x25519-sha512@tinyssh.org"
#define COMP_NONE 0
/* pre-auth compression (COMP_ZLIB) is only supported in the client */
#define COMP_ZLIB 1
#define COMP_DELAYED 2
#define CURVE25519_SIZE 32
enum kex_init_proposals {
PROPOSAL_KEX_ALGS,
PROPOSAL_SERVER_HOST_KEY_ALGS,
PROPOSAL_ENC_ALGS_CTOS,
PROPOSAL_ENC_ALGS_STOC,
PROPOSAL_MAC_ALGS_CTOS,
PROPOSAL_MAC_ALGS_STOC,
PROPOSAL_COMP_ALGS_CTOS,
PROPOSAL_COMP_ALGS_STOC,
PROPOSAL_LANG_CTOS,
PROPOSAL_LANG_STOC,
PROPOSAL_MAX
};
enum kex_modes {
MODE_IN,
MODE_OUT,
MODE_MAX
};
enum kex_exchange {
KEX_DH_GRP1_SHA1,
KEX_DH_GRP14_SHA1,
KEX_DH_GRP14_SHA256,
KEX_DH_GRP16_SHA512,
KEX_DH_GRP18_SHA512,
KEX_DH_GEX_SHA1,
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
KEX_C25519_SHA256,
+ KEX_KEM_SNTRUP4591761X25519_SHA512,
KEX_MAX
};
#define KEX_INIT_SENT 0x0001
+#define KEX_INITIAL 0x0002
struct sshenc {
char *name;
const struct sshcipher *cipher;
int enabled;
u_int key_len;
u_int iv_len;
u_int block_size;
u_char *key;
u_char *iv;
};
struct sshcomp {
u_int type;
int enabled;
char *name;
};
struct newkeys {
struct sshenc enc;
struct sshmac mac;
struct sshcomp comp;
};
struct ssh;
struct kex {
u_char *session_id;
size_t session_id_len;
struct newkeys *newkeys[MODE_MAX];
u_int we_need;
u_int dh_need;
int server;
char *name;
char *hostkey_alg;
int hostkey_type;
int hostkey_nid;
u_int kex_type;
char *server_sig_algs;
int ext_info_c;
struct sshbuf *my;
struct sshbuf *peer;
+ struct sshbuf *client_version;
+ struct sshbuf *server_version;
sig_atomic_t done;
u_int flags;
int hash_alg;
int ec_nid;
- char *client_version_string;
- char *server_version_string;
char *failed_choice;
int (*verify_host_key)(struct sshkey *, struct ssh *);
struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
struct sshkey *(*load_host_private_key)(int, int, struct ssh *);
int (*host_key_index)(struct sshkey *, int, struct ssh *);
- int (*sign)(struct sshkey *, struct sshkey *, u_char **, size_t *,
- const u_char *, size_t, const char *, u_int);
+ int (*sign)(struct ssh *, struct sshkey *, struct sshkey *,
+ u_char **, size_t *, const u_char *, size_t, const char *);
int (*kex[KEX_MAX])(struct ssh *);
/* kex specific state */
DH *dh; /* DH */
u_int min, max, nbits; /* GEX */
EC_KEY *ec_client_key; /* ECDH */
const EC_GROUP *ec_group; /* ECDH */
- u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 */
+ u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */
u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */
+ u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */
+ struct sshbuf *client_pub;
};
int kex_names_valid(const char *);
char *kex_alg_list(char);
char *kex_names_cat(const char *, const char *);
int kex_assemble_names(char **, const char *, const char *);
-int 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]);
void kex_free_newkeys(struct newkeys *);
void kex_free(struct kex *);
int kex_buf2prop(struct sshbuf *, int *, char ***);
int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]);
void kex_prop_free(char **);
+int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **);
+int kex_verify_host_key(struct ssh *, struct sshkey *);
int kex_send_kexinit(struct ssh *);
int kex_input_kexinit(int, u_int32_t, struct ssh *);
int kex_input_ext_info(int, u_int32_t, struct ssh *);
int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
-int kex_derive_keys_bn(struct ssh *, u_char *, u_int, const BIGNUM *);
int kex_send_newkeys(struct ssh *);
int kex_start_rekex(struct ssh *);
-int kexdh_client(struct ssh *);
-int kexdh_server(struct ssh *);
int kexgex_client(struct ssh *);
int kexgex_server(struct ssh *);
-int kexecdh_client(struct ssh *);
-int kexecdh_server(struct ssh *);
-int kexc25519_client(struct ssh *);
-int kexc25519_server(struct ssh *);
+int kex_gen_client(struct ssh *);
+int kex_gen_server(struct ssh *);
+
+int kex_dh_keypair(struct kex *);
+int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
+ struct sshbuf **);
+int kex_dh_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
+
+int kex_ecdh_keypair(struct kex *);
+int kex_ecdh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
+ struct sshbuf **);
+int kex_ecdh_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
+
+int kex_c25519_keypair(struct kex *);
+int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
+ struct sshbuf **);
+int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
+
+int kex_kem_sntrup4591761x25519_keypair(struct kex *);
+int kex_kem_sntrup4591761x25519_enc(struct kex *, const struct sshbuf *,
+ struct sshbuf **, struct sshbuf **);
+int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *,
+ struct sshbuf **);
-int kex_dh_hash(int, const char *, const char *,
- const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
- const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
+int kex_dh_keygen(struct kex *);
+int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *);
-int kexgex_hash(int, const char *, const char *,
- const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
+int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
+ const struct sshbuf *, const struct sshbuf *, const struct sshbuf *,
int, int, int,
const BIGNUM *, const BIGNUM *, const BIGNUM *,
- const BIGNUM *, const BIGNUM *,
+ const BIGNUM *, const u_char *, size_t,
u_char *, size_t *);
-int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *,
- 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 *);
-
-int kex_c25519_hash(int, const char *, const char *,
- 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, u_char *, size_t *);
-
void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
int kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
+int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
+ const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int)
+ __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
+ __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
-void dump_digest(char *, u_char *, int);
+void dump_digest(const char *, const u_char *, int);
#endif
#if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC)
# undef EC_KEY
# undef EC_GROUP
# undef EC_POINT
#endif
#endif
diff --git a/kexc25519.c b/kexc25519.c
index 0897b8c5190a..f13d766d7247 100644
--- a/kexc25519.c
+++ b/kexc25519.c
@@ -1,133 +1,199 @@
-/* $OpenBSD: kexc25519.c,v 1.10 2016/05/02 08:49:03 djm Exp $ */
+/* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */
/*
- * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
* Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
-#include <signal.h>
+#include <stdio.h>
#include <string.h>
+#include <signal.h>
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-
-#include "sshbuf.h"
-#include "ssh2.h"
#include "sshkey.h"
-#include "cipher.h"
#include "kex.h"
-#include "log.h"
+#include "sshbuf.h"
#include "digest.h"
#include "ssherr.h"
+#include "ssh2.h"
extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE],
const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE])
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)))
__attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE)));
void
kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
{
static const u_char basepoint[CURVE25519_SIZE] = {9};
arc4random_buf(key, CURVE25519_SIZE);
crypto_scalarmult_curve25519(pub, key, basepoint);
}
int
-kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
- const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
+kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
+ const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw)
{
u_char shared_key[CURVE25519_SIZE];
+ u_char zero[CURVE25519_SIZE];
int r;
- /* Check for all-zero public key */
- explicit_bzero(shared_key, CURVE25519_SIZE);
- if (timingsafe_bcmp(pub, shared_key, CURVE25519_SIZE) == 0)
+ crypto_scalarmult_curve25519(shared_key, key, pub);
+
+ /* Check for all-zero shared secret */
+ explicit_bzero(zero, CURVE25519_SIZE);
+ if (timingsafe_bcmp(zero, shared_key, CURVE25519_SIZE) == 0)
return SSH_ERR_KEY_INVALID_EC_VALUE;
- crypto_scalarmult_curve25519(shared_key, key, pub);
#ifdef DEBUG_KEXECDH
dump_digest("shared secret", shared_key, CURVE25519_SIZE);
#endif
- sshbuf_reset(out);
- r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
+ if (raw)
+ r = sshbuf_put(out, shared_key, CURVE25519_SIZE);
+ else
+ r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
explicit_bzero(shared_key, CURVE25519_SIZE);
return r;
}
int
-kex_c25519_hash(
- int hash_alg,
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
- const u_char client_dh_pub[CURVE25519_SIZE],
- const u_char server_dh_pub[CURVE25519_SIZE],
- const u_char *shared_secret, size_t secretlen,
- u_char *hash, size_t *hashlen)
+kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
+ const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
+{
+ return kexc25519_shared_key_ext(key, pub, out, 0);
+}
+
+int
+kex_c25519_keypair(struct kex *kex)
{
- struct sshbuf *b;
+ struct sshbuf *buf = NULL;
+ u_char *cp = NULL;
int r;
- if (*hashlen < ssh_digest_bytes(hash_alg))
- return SSH_ERR_INVALID_ARGUMENT;
- if ((b = sshbuf_new()) == NULL)
+ if ((buf = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) < 0 ||
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 ||
- (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 ||
- (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 ||
- (r = sshbuf_put(b, shared_secret, secretlen)) < 0) {
- sshbuf_free(b);
- return r;
+ if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0)
+ goto out;
+ kexc25519_keygen(kex->c25519_client_key, cp);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
+#endif
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob,
+ struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
+{
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *buf = NULL;
+ const u_char *client_pub;
+ u_char *server_pub;
+ u_char server_key[CURVE25519_SIZE];
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ if (sshbuf_len(client_blob) != CURVE25519_SIZE) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
}
-#ifdef DEBUG_KEX
- sshbuf_dump(b, stderr);
+ client_pub = sshbuf_ptr(client_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE);
#endif
- if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
- sshbuf_free(b);
- return SSH_ERR_LIBCRYPTO_ERROR;
+ /* allocate space for encrypted KEM key and ECDH pub key */
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
- sshbuf_free(b);
- *hashlen = ssh_digest_bytes(hash_alg);
-#ifdef DEBUG_KEX
- dump_digest("hash", hash, *hashlen);
+ if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0)
+ goto out;
+ kexc25519_keygen(server_key, server_pub);
+ /* allocate shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
#endif
- return 0;
+ *server_blobp = server_blob;
+ *shared_secretp = buf;
+ server_blob = NULL;
+ buf = NULL;
+ out:
+ explicit_bzero(server_key, sizeof(server_key));
+ sshbuf_free(server_blob);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob,
+ struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ const u_char *server_pub;
+ int r;
+
+ *shared_secretp = NULL;
+
+ if (sshbuf_len(server_blob) != CURVE25519_SIZE) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ server_pub = sshbuf_ptr(server_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
+#endif
+ /* shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
+ buf, 0)) < 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
}
diff --git a/kexc25519c.c b/kexc25519c.c
deleted file mode 100644
index a8d92149c3fd..000000000000
--- a/kexc25519c.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* $OpenBSD: kexc25519c.c,v 1.9 2017/12/18 02:25:15 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "ssh2.h"
-#include "sshbuf.h"
-#include "digest.h"
-#include "ssherr.h"
-
-static int
-input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh);
-
-int
-kexc25519_client(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- int r;
-
- kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey);
-#ifdef DEBUG_KEXECDH
- dump_digest("client private key:", kex->c25519_client_key,
- sizeof(kex->c25519_client_key));
-#endif
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
- (r = sshpkt_put_string(ssh, kex->c25519_client_pubkey,
- sizeof(kex->c25519_client_pubkey))) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- return r;
-
- debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_c25519_reply);
- return 0;
-}
-
-static int
-input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- struct sshkey *server_host_key = NULL;
- struct sshbuf *shared_secret = NULL;
- u_char *server_pubkey = NULL;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, pklen, sbloblen, hashlen;
- int r;
-
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
-
- /* hostkey */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
- goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-
- /* Q_S, server public key */
- /* signed H */
- if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 ||
- (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
- if (pklen != CURVE25519_SIZE) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-
-#ifdef DEBUG_KEXECDH
- dump_digest("server public key:", server_pubkey, CURVE25519_SIZE);
-#endif
-
- if ((shared_secret = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = kexc25519_shared_key(kex->c25519_client_key, server_pubkey,
- shared_secret)) < 0)
- goto out;
-
- /* calc and verify H */
- hashlen = sizeof(hash);
- if ((r = kex_c25519_hash(
- kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
- kex->c25519_client_pubkey,
- server_pubkey,
- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
- hash, &hashlen)) < 0)
- goto out;
-
- if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
- kex->hostkey_alg, ssh->compat)) != 0)
- goto out;
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
-out:
- explicit_bzero(hash, sizeof(hash));
- explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
- free(server_host_key_blob);
- free(server_pubkey);
- free(signature);
- sshkey_free(server_host_key);
- sshbuf_free(shared_secret);
- return r;
-}
diff --git a/kexc25519s.c b/kexc25519s.c
deleted file mode 100644
index 0800a7a4bcf4..000000000000
--- a/kexc25519s.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* $OpenBSD: kexc25519s.c,v 1.11 2017/05/31 04:19:28 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
- *
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "ssh2.h"
-#include "sshbuf.h"
-#include "ssherr.h"
-
-static int input_kex_c25519_init(int, u_int32_t, struct ssh *);
-
-int
-kexc25519_server(struct ssh *ssh)
-{
- debug("expecting SSH2_MSG_KEX_ECDH_INIT");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_c25519_init);
- return 0;
-}
-
-static int
-input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- struct sshkey *server_host_private, *server_host_public;
- struct sshbuf *shared_secret = NULL;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char server_key[CURVE25519_SIZE];
- u_char *client_pubkey = NULL;
- u_char server_pubkey[CURVE25519_SIZE];
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, pklen, sbloblen, hashlen;
- int r;
-
- /* generate private key */
- kexc25519_keygen(server_key, server_pubkey);
-#ifdef DEBUG_KEXECDH
- dump_digest("server private key:", server_key, sizeof(server_key));
-#endif
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
- goto out;
- }
-
- if ((r = sshpkt_get_string(ssh, &client_pubkey, &pklen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
- if (pklen != CURVE25519_SIZE) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-#ifdef DEBUG_KEXECDH
- dump_digest("client public key:", client_pubkey, CURVE25519_SIZE);
-#endif
-
- if ((shared_secret = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = kexc25519_shared_key(server_key, client_pubkey,
- shared_secret)) < 0)
- goto out;
-
- /* calc H */
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
- goto out;
- hashlen = sizeof(hash);
- if ((r = kex_c25519_hash(
- kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
- client_pubkey,
- server_pubkey,
- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
- hash, &hashlen)) < 0)
- goto out;
-
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- if ((r = kex->sign(server_host_private, server_host_public, &signature,
- &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
- goto out;
-
- /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_string(ssh, server_pubkey, sizeof(server_pubkey))) != 0 ||
- (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-
- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
-out:
- explicit_bzero(hash, sizeof(hash));
- explicit_bzero(server_key, sizeof(server_key));
- free(server_host_key_blob);
- free(signature);
- free(client_pubkey);
- sshbuf_free(shared_secret);
- return r;
-}
diff --git a/kexdh.c b/kexdh.c
index e6925b186d82..67133e339481 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,96 +1,201 @@
-/* $OpenBSD: kexdh.c,v 1.26 2016/05/02 10:26:04 djm Exp $ */
+/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */
/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <signal.h>
-
-#include <openssl/evp.h>
+#include <stdio.h>
+#include <string.h>
#include "openbsd-compat/openssl-compat.h"
+#include <openssl/dh.h>
-#include "ssh2.h"
#include "sshkey.h"
-#include "cipher.h"
#include "kex.h"
-#include "ssherr.h"
#include "sshbuf.h"
#include "digest.h"
+#include "ssherr.h"
+#include "dh.h"
int
-kex_dh_hash(
- int hash_alg,
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
- const BIGNUM *client_dh_pub,
- const BIGNUM *server_dh_pub,
- const BIGNUM *shared_secret,
- u_char *hash, size_t *hashlen)
+kex_dh_keygen(struct kex *kex)
{
- struct sshbuf *b;
- int r;
-
- if (*hashlen < ssh_digest_bytes(hash_alg))
+ switch (kex->kex_type) {
+ case KEX_DH_GRP1_SHA1:
+ kex->dh = dh_new_group1();
+ break;
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ kex->dh = dh_new_group14();
+ break;
+ case KEX_DH_GRP16_SHA512:
+ kex->dh = dh_new_group16();
+ break;
+ case KEX_DH_GRP18_SHA512:
+ kex->dh = dh_new_group18();
+ break;
+ default:
return SSH_ERR_INVALID_ARGUMENT;
- if ((b = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
- (r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
- (r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
- (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
- sshbuf_free(b);
- return r;
}
-#ifdef DEBUG_KEX
- sshbuf_dump(b, stderr);
+ if (kex->dh == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ return (dh_gen_key(kex->dh, kex->we_need * 8));
+}
+
+int
+kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
+{
+ BIGNUM *shared_secret = NULL;
+ u_char *kbuf = NULL;
+ size_t klen = 0;
+ int kout, r;
+
+#ifdef DEBUG_KEXDH
+ fprintf(stderr, "dh_pub= ");
+ BN_print_fp(stderr, dh_pub);
+ fprintf(stderr, "\n");
+ debug("bits %d", BN_num_bits(dh_pub));
+ DHparams_print_fp(stderr, kex->dh);
+ fprintf(stderr, "\n");
#endif
- if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
- sshbuf_free(b);
- return SSH_ERR_LIBCRYPTO_ERROR;
+
+ if (!dh_pub_is_valid(kex->dh, dh_pub)) {
+ r = SSH_ERR_MESSAGE_INCOMPLETE;
+ goto out;
+ }
+ klen = DH_size(kex->dh);
+ if ((kbuf = malloc(klen)) == NULL ||
+ (shared_secret = BN_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
+ BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
}
- sshbuf_free(b);
- *hashlen = ssh_digest_bytes(hash_alg);
-#ifdef DEBUG_KEX
- dump_digest("hash", hash, *hashlen);
+#ifdef DEBUG_KEXDH
+ dump_digest("shared secret", kbuf, kout);
#endif
- return 0;
+ r = sshbuf_put_bignum2(out, shared_secret);
+ out:
+ freezero(kbuf, klen);
+ BN_clear_free(shared_secret);
+ return r;
+}
+
+int
+kex_dh_keypair(struct kex *kex)
+{
+ const BIGNUM *pub_key;
+ struct sshbuf *buf = NULL;
+ int r;
+
+ if ((r = kex_dh_keygen(kex)) != 0)
+ return r;
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ if ((buf = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 ||
+ (r = sshbuf_get_u32(buf, NULL)) != 0)
+ goto out;
+#ifdef DEBUG_KEXDH
+ DHparams_print_fp(stderr, kex->dh);
+ fprintf(stderr, "pub= ");
+ BN_print_fp(stderr, pub_key);
+ fprintf(stderr, "\n");
+#endif
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob,
+ struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
+{
+ const BIGNUM *pub_key;
+ struct sshbuf *server_blob = NULL;
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ if ((r = kex_dh_keygen(kex)) != 0)
+ goto out;
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 ||
+ (r = sshbuf_get_u32(server_blob, NULL)) != 0)
+ goto out;
+ if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0)
+ goto out;
+ *server_blobp = server_blob;
+ server_blob = NULL;
+ out:
+ DH_free(kex->dh);
+ kex->dh = NULL;
+ sshbuf_free(server_blob);
+ return r;
+}
+
+int
+kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
+ struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ BIGNUM *dh_pub = NULL;
+ int r;
+
+ *shared_secretp = NULL;
+
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dh_pub)) != 0)
+ goto out;
+ sshbuf_reset(buf);
+ if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0)
+ goto out;
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ DH_free(kex->dh);
+ kex->dh = NULL;
+ sshbuf_free(buf);
+ return r;
}
#endif /* WITH_OPENSSL */
diff --git a/kexdhc.c b/kexdhc.c
deleted file mode 100644
index 8b56377ad09d..000000000000
--- a/kexdhc.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/* $OpenBSD: kexdhc.c,v 1.22 2018/02/07 02:06:51 jsing Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#ifdef WITH_OPENSSL
-
-#include <sys/types.h>
-
-#include <openssl/dh.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include "openbsd-compat/openssl-compat.h"
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_dh(int, u_int32_t, struct ssh *);
-
-int
-kexdh_client(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- int r;
- const BIGNUM *pub_key;
-
- /* generate and send 'e', client DH public key */
- switch (kex->kex_type) {
- case KEX_DH_GRP1_SHA1:
- kex->dh = dh_new_group1();
- break;
- case KEX_DH_GRP14_SHA1:
- case KEX_DH_GRP14_SHA256:
- kex->dh = dh_new_group14();
- break;
- case KEX_DH_GRP16_SHA512:
- kex->dh = dh_new_group16();
- break;
- case KEX_DH_GRP18_SHA512:
- kex->dh = dh_new_group18();
- break;
- default:
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if (kex->dh == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- debug("sending SSH2_MSG_KEXDH_INIT");
- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
- goto out;
- DH_get0_key(kex->dh, &pub_key, NULL);
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-#ifdef DEBUG_KEXDH
- DHparams_print_fp(stderr, kex->dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, pub_key);
- fprintf(stderr, "\n");
-#endif
- debug("expecting SSH2_MSG_KEXDH_REPLY");
- ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh);
- r = 0;
- out:
- return r;
-}
-
-static int
-input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
- const BIGNUM *pub_key;
- struct sshkey *server_host_key = NULL;
- u_char *kbuf = NULL, *server_host_key_blob = NULL, *signature = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t klen = 0, slen, sbloblen, hashlen;
- int kout, r;
-
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- /* key, cert */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
- goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
- /* DH parameter f, server public DH key */
- if ((dh_server_pub = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- /* signed H */
- if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 ||
- (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
- sshpkt_disconnect(ssh, "bad server public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
-
- /* calc and verify H */
- DH_get0_key(kex->dh, &pub_key, NULL);
- hashlen = sizeof(hash);
- if ((r = kex_dh_hash(
- kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
- pub_key,
- dh_server_pub,
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
- kex->hostkey_alg, ssh->compat)) != 0)
- goto out;
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- DH_free(kex->dh);
- kex->dh = NULL;
- BN_clear_free(dh_server_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- BN_clear_free(shared_secret);
- sshkey_free(server_host_key);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* WITH_OPENSSL */
diff --git a/kexdhs.c b/kexdhs.c
deleted file mode 100644
index 337aab5beb41..000000000000
--- a/kexdhs.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* $OpenBSD: kexdhs.c,v 1.27 2018/04/10 00:10:49 djm Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#ifdef WITH_OPENSSL
-
-#include <sys/types.h>
-
-#include <stdarg.h>
-#include <string.h>
-#include <signal.h>
-
-#include <openssl/dh.h>
-
-#include "openbsd-compat/openssl-compat.h"
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_dh_init(int, u_int32_t, struct ssh *);
-
-int
-kexdh_server(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- int r;
-
- /* generate server DH public key */
- switch (kex->kex_type) {
- case KEX_DH_GRP1_SHA1:
- kex->dh = dh_new_group1();
- break;
- case KEX_DH_GRP14_SHA1:
- case KEX_DH_GRP14_SHA256:
- kex->dh = dh_new_group14();
- break;
- case KEX_DH_GRP16_SHA512:
- kex->dh = dh_new_group16();
- break;
- case KEX_DH_GRP18_SHA512:
- kex->dh = dh_new_group18();
- break;
- default:
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if (kex->dh == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
- goto out;
-
- debug("expecting SSH2_MSG_KEXDH_INIT");
- ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init);
- r = 0;
- out:
- return r;
-}
-
-int
-input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
- const BIGNUM *pub_key;
- struct sshkey *server_host_public, *server_host_private;
- u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t sbloblen, slen;
- size_t klen = 0, hashlen;
- int kout, r;
-
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
- goto out;
- }
-
- /* key, cert */
- if ((dh_client_pub = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- DH_get0_key(kex->dh, &pub_key, NULL);
- if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_client_pub= ");
- BN_print_fp(stderr, dh_client_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_client_pub));
- DHparams_print_fp(stderr, kex->dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, pub_key);
- fprintf(stderr, "\n");
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
- sshpkt_disconnect(ssh, "bad client public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
- goto out;
- /* calc H */
- hashlen = sizeof(hash);
- if ((r = kex_dh_hash(
- kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
- dh_client_pub,
- pub_key,
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- if ((r = kex->sign(server_host_private, server_host_public, &signature,
- &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
- goto out;
-
- /* destroy_sensitive_data(); */
-
- /* send server hostkey, DH pubkey 'f' and signed H */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */
- (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- DH_free(kex->dh);
- kex->dh = NULL;
- BN_clear_free(dh_client_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- BN_clear_free(shared_secret);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* WITH_OPENSSL */
diff --git a/kexecdh.c b/kexecdh.c
index 2a4fec6b124c..0aeab2e9b13b 100644
--- a/kexecdh.c
+++ b/kexecdh.c
@@ -1,100 +1,211 @@
-/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */
/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
#include <sys/types.h>
-#include <signal.h>
+#include <stdio.h>
#include <string.h>
+#include <signal.h>
-#include <openssl/bn.h>
-#include <openssl/evp.h>
-#include <openssl/ec.h>
#include <openssl/ecdh.h>
-#include "ssh2.h"
#include "sshkey.h"
-#include "cipher.h"
#include "kex.h"
#include "sshbuf.h"
#include "digest.h"
#include "ssherr.h"
+static int
+kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
+ const EC_GROUP *, struct sshbuf **);
+
int
-kex_ecdh_hash(
- int hash_alg,
- const EC_GROUP *ec_group,
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
- const EC_POINT *client_dh_pub,
- const EC_POINT *server_dh_pub,
- const BIGNUM *shared_secret,
- u_char *hash, size_t *hashlen)
+kex_ecdh_keypair(struct kex *kex)
{
- struct sshbuf *b;
+ EC_KEY *client_key = NULL;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ struct sshbuf *buf = NULL;
int r;
- if (*hashlen < ssh_digest_bytes(hash_alg))
- return SSH_ERR_INVALID_ARGUMENT;
- if ((b = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
- /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
- (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
- (r = sshbuf_put_ec(b, client_dh_pub, ec_group)) != 0 ||
- (r = sshbuf_put_ec(b, server_dh_pub, ec_group)) != 0 ||
- (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
- sshbuf_free(b);
- return r;
+ if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (EC_KEY_generate_key(client_key) != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ group = EC_KEY_get0_group(client_key);
+ public_key = EC_KEY_get0_public_key(client_key);
+
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
-#ifdef DEBUG_KEX
- sshbuf_dump(b, stderr);
+ if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 ||
+ (r = sshbuf_get_u32(buf, NULL)) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ fputs("client private key:\n", stderr);
+ sshkey_dump_ec_key(client_key);
#endif
- if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
- sshbuf_free(b);
- return SSH_ERR_LIBCRYPTO_ERROR;
+ kex->ec_client_key = client_key;
+ kex->ec_group = group;
+ client_key = NULL; /* owned by the kex */
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ EC_KEY_free(client_key);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
+ struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
+{
+ const EC_GROUP *group;
+ const EC_POINT *pub_key;
+ EC_KEY *server_key = NULL;
+ struct sshbuf *server_blob = NULL;
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
- sshbuf_free(b);
- *hashlen = ssh_digest_bytes(hash_alg);
-#ifdef DEBUG_KEX
- dump_digest("hash", hash, *hashlen);
+ if (EC_KEY_generate_key(server_key) != 1) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ group = EC_KEY_get0_group(server_key);
+
+#ifdef DEBUG_KEXECDH
+ fputs("server private key:\n", stderr);
+ sshkey_dump_ec_key(server_key);
#endif
- return 0;
+ pub_key = EC_KEY_get0_public_key(server_key);
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 ||
+ (r = sshbuf_get_u32(server_blob, NULL)) != 0)
+ goto out;
+ if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group,
+ shared_secretp)) != 0)
+ goto out;
+ *server_blobp = server_blob;
+ server_blob = NULL;
+ out:
+ EC_KEY_free(server_key);
+ sshbuf_free(server_blob);
+ return r;
+}
+
+static int
+kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
+ EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ BIGNUM *shared_secret = NULL;
+ EC_POINT *dh_pub = NULL;
+ u_char *kbuf = NULL;
+ size_t klen = 0;
+ int r;
+
+ *shared_secretp = NULL;
+
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
+ goto out;
+ if ((dh_pub = EC_POINT_new(group)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
+ goto out;
+ }
+ sshbuf_reset(buf);
+
+#ifdef DEBUG_KEXECDH
+ fputs("public key:\n", stderr);
+ sshkey_dump_ec_point(group, dh_pub);
+#endif
+ if (sshkey_ec_validate_public(group, dh_pub) != 0) {
+ r = SSH_ERR_MESSAGE_INCOMPLETE;
+ goto out;
+ }
+ klen = (EC_GROUP_get_degree(group) + 7) / 8;
+ if ((kbuf = malloc(klen)) == NULL ||
+ (shared_secret = BN_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+#ifdef DEBUG_KEXECDH
+ dump_digest("shared secret", kbuf, klen);
+#endif
+ if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
+ goto out;
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ EC_POINT_clear_free(dh_pub);
+ BN_clear_free(shared_secret);
+ freezero(kbuf, klen);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
+ struct sshbuf **shared_secretp)
+{
+ int r;
+
+ r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key,
+ kex->ec_group, shared_secretp);
+ EC_KEY_free(kex->ec_client_key);
+ kex->ec_client_key = NULL;
+ return r;
}
#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
diff --git a/kexecdhc.c b/kexecdhc.c
deleted file mode 100644
index ac146a362ee0..000000000000
--- a/kexecdhc.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/* $OpenBSD: kexecdhc.c,v 1.13 2018/02/07 02:06:51 jsing Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-
-#include <openssl/ecdh.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
-#include "ssh2.h"
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_ecdh_reply(int, u_int32_t, struct ssh *);
-
-int
-kexecdh_client(struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- EC_KEY *client_key = NULL;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- int r;
-
- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (EC_KEY_generate_key(client_key) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- group = EC_KEY_get0_group(client_key);
- public_key = EC_KEY_get0_public_key(client_key);
-
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
- (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
- debug("sending SSH2_MSG_KEX_ECDH_INIT");
-
-#ifdef DEBUG_KEXECDH
- fputs("client private key:\n", stderr);
- sshkey_dump_ec_key(client_key);
-#endif
- kex->ec_client_key = client_key;
- kex->ec_group = group;
- client_key = NULL; /* owned by the kex */
-
- debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_ecdh_reply);
- r = 0;
- out:
- EC_KEY_free(client_key);
- return r;
-}
-
-static int
-input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- const EC_GROUP *group;
- EC_POINT *server_public = NULL;
- EC_KEY *client_key;
- BIGNUM *shared_secret = NULL;
- struct sshkey *server_host_key = NULL;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char *kbuf = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, sbloblen;
- size_t klen = 0, hashlen;
- int r;
-
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- group = kex->ec_group;
- client_key = kex->ec_client_key;
-
- /* hostkey */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
- goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
-
- /* Q_S, server public key */
- /* signed H */
- if ((server_public = EC_POINT_new(group)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_ec(ssh, server_public, group)) != 0 ||
- (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-
-#ifdef DEBUG_KEXECDH
- fputs("server public key:\n", stderr);
- sshkey_dump_ec_point(group, server_public);
-#endif
- if (sshkey_ec_validate_public(group, server_public) != 0) {
- sshpkt_disconnect(ssh, "invalid server public key");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (ECDH_compute_key(kbuf, klen, server_public,
- client_key, NULL) != (int)klen ||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-
-#ifdef DEBUG_KEXECDH
- dump_digest("shared secret", kbuf, klen);
-#endif
- /* calc and verify H */
- hashlen = sizeof(hash);
- if ((r = kex_ecdh_hash(
- kex->hash_alg,
- group,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
- EC_KEY_get0_public_key(client_key),
- server_public,
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- if ((r = sshkey_verify(server_host_key, signature, slen, hash,
- hashlen, kex->hostkey_alg, ssh->compat)) != 0)
- goto out;
-
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- EC_KEY_free(kex->ec_client_key);
- kex->ec_client_key = NULL;
- EC_POINT_clear_free(server_public);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- BN_clear_free(shared_secret);
- sshkey_free(server_host_key);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
-
diff --git a/kexecdhs.c b/kexecdhs.c
deleted file mode 100644
index af4f30309971..000000000000
--- a/kexecdhs.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* $OpenBSD: kexecdhs.c,v 1.17 2018/02/07 02:06:51 jsing Exp $ */
-/*
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2010 Damien Miller. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "includes.h"
-
-#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
-
-#include <sys/types.h>
-#include <string.h>
-#include <signal.h>
-
-#include <openssl/ecdh.h>
-
-#include "sshkey.h"
-#include "cipher.h"
-#include "digest.h"
-#include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "ssh2.h"
-
-#include "dispatch.h"
-#include "compat.h"
-#include "ssherr.h"
-#include "sshbuf.h"
-
-static int input_kex_ecdh_init(int, u_int32_t, struct ssh *);
-
-int
-kexecdh_server(struct ssh *ssh)
-{
- debug("expecting SSH2_MSG_KEX_ECDH_INIT");
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_ecdh_init);
- return 0;
-}
-
-static int
-input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh)
-{
- struct kex *kex = ssh->kex;
- EC_POINT *client_public;
- EC_KEY *server_key = NULL;
- const EC_GROUP *group;
- const EC_POINT *public_key;
- BIGNUM *shared_secret = NULL;
- struct sshkey *server_host_private, *server_host_public;
- u_char *server_host_key_blob = NULL, *signature = NULL;
- u_char *kbuf = NULL;
- u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t slen, sbloblen;
- size_t klen = 0, hashlen;
- int r;
-
- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (EC_KEY_generate_key(server_key) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- group = EC_KEY_get0_group(server_key);
-
-#ifdef DEBUG_KEXECDH
- fputs("server private key:\n", stderr);
- sshkey_dump_ec_key(server_key);
-#endif
-
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
- goto out;
- }
- if ((client_public = EC_POINT_new(group)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_ec(ssh, client_public, group)) != 0 ||
- (r = sshpkt_get_end(ssh)) != 0)
- goto out;
-
-#ifdef DEBUG_KEXECDH
- fputs("client public key:\n", stderr);
- sshkey_dump_ec_point(group, client_public);
-#endif
- if (sshkey_ec_validate_public(group, client_public) != 0) {
- sshpkt_disconnect(ssh, "invalid client public key");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- /* Calculate shared_secret */
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (ECDH_compute_key(kbuf, klen, client_public,
- server_key, NULL) != (int)klen ||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
-
-#ifdef DEBUG_KEXECDH
- dump_digest("shared secret", kbuf, klen);
-#endif
- /* calc H */
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
- goto out;
- hashlen = sizeof(hash);
- if ((r = kex_ecdh_hash(
- kex->hash_alg,
- group,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
- client_public,
- EC_KEY_get0_public_key(server_key),
- shared_secret,
- hash, &hashlen)) != 0)
- goto out;
-
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- /* sign H */
- if ((r = kex->sign(server_host_private, server_host_public, &signature,
- &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
- goto out;
-
- /* destroy_sensitive_data(); */
-
- public_key = EC_KEY_get0_public_key(server_key);
- /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
- if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
- (r = sshpkt_put_ec(ssh, public_key, group)) != 0 ||
- (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- goto out;
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
- r = kex_send_newkeys(ssh);
- out:
- explicit_bzero(hash, sizeof(hash));
- EC_KEY_free(kex->ec_client_key);
- kex->ec_client_key = NULL;
- EC_KEY_free(server_key);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- BN_clear_free(shared_secret);
- free(server_host_key_blob);
- free(signature);
- return r;
-}
-#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
-
diff --git a/kexgen.c b/kexgen.c
new file mode 100644
index 000000000000..2abbb9ef6f04
--- /dev/null
+++ b/kexgen.c
@@ -0,0 +1,339 @@
+/* $OpenBSD: kexgen.c,v 1.2 2019/01/23 00:30:41 djm Exp $ */
+/*
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "sshkey.h"
+#include "kex.h"
+#include "log.h"
+#include "packet.h"
+#include "ssh2.h"
+#include "sshbuf.h"
+#include "digest.h"
+#include "ssherr.h"
+
+static int input_kex_gen_init(int, u_int32_t, struct ssh *);
+static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh);
+
+static int
+kex_gen_hash(
+ int hash_alg,
+ const struct sshbuf *client_version,
+ const struct sshbuf *server_version,
+ const struct sshbuf *client_kexinit,
+ const struct sshbuf *server_kexinit,
+ const struct sshbuf *server_host_key_blob,
+ const struct sshbuf *client_pub,
+ const struct sshbuf *server_pub,
+ const struct sshbuf *shared_secret,
+ u_char *hash, size_t *hashlen)
+{
+ struct sshbuf *b;
+ int r;
+
+ if (*hashlen < ssh_digest_bytes(hash_alg))
+ return SSH_ERR_INVALID_ARGUMENT;
+ if ((b = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = sshbuf_put_stringb(b, client_version)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_version)) != 0 ||
+ /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
+ (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 ||
+ (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
+ (r = sshbuf_putb(b, client_kexinit)) != 0 ||
+ (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 1)) != 0 ||
+ (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
+ (r = sshbuf_putb(b, server_kexinit)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 ||
+ (r = sshbuf_put_stringb(b, client_pub)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_pub)) != 0 ||
+ (r = sshbuf_putb(b, shared_secret)) != 0) {
+ sshbuf_free(b);
+ return r;
+ }
+#ifdef DEBUG_KEX
+ sshbuf_dump(b, stderr);
+#endif
+ if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
+ sshbuf_free(b);
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ }
+ sshbuf_free(b);
+ *hashlen = ssh_digest_bytes(hash_alg);
+#ifdef DEBUG_KEX
+ dump_digest("hash", hash, *hashlen);
+#endif
+ return 0;
+}
+
+int
+kex_gen_client(struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ int r;
+
+ switch (kex->kex_type) {
+#ifdef WITH_OPENSSL
+ case KEX_DH_GRP1_SHA1:
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ case KEX_DH_GRP16_SHA512:
+ case KEX_DH_GRP18_SHA512:
+ r = kex_dh_keypair(kex);
+ break;
+ case KEX_ECDH_SHA2:
+ r = kex_ecdh_keypair(kex);
+ break;
+#endif
+ case KEX_C25519_SHA256:
+ r = kex_c25519_keypair(kex);
+ break;
+ case KEX_KEM_SNTRUP4591761X25519_SHA512:
+ r = kex_kem_sntrup4591761x25519_keypair(kex);
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ if (r != 0)
+ return r;
+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ return r;
+ debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_gen_reply);
+ return 0;
+}
+
+static int
+input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ struct sshkey *server_host_key = NULL;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *tmp = NULL, *server_host_key_blob = NULL;
+ u_char *signature = NULL;
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t slen, hashlen;
+ int r;
+
+ /* hostkey */
+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
+ goto out;
+ /* sshkey_fromb() consumes its buffer, so make a copy */
+ if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshkey_fromb(tmp, &server_host_key)) != 0)
+ goto out;
+ if ((r = kex_verify_host_key(ssh, server_host_key)) != 0)
+ goto out;
+
+ /* Q_S, server public key */
+ /* signed H */
+ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
+ (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
+
+ /* compute shared secret */
+ switch (kex->kex_type) {
+#ifdef WITH_OPENSSL
+ case KEX_DH_GRP1_SHA1:
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ case KEX_DH_GRP16_SHA512:
+ case KEX_DH_GRP18_SHA512:
+ r = kex_dh_dec(kex, server_blob, &shared_secret);
+ break;
+ case KEX_ECDH_SHA2:
+ r = kex_ecdh_dec(kex, server_blob, &shared_secret);
+ break;
+#endif
+ case KEX_C25519_SHA256:
+ r = kex_c25519_dec(kex, server_blob, &shared_secret);
+ break;
+ case KEX_KEM_SNTRUP4591761X25519_SHA512:
+ r = kex_kem_sntrup4591761x25519_dec(kex, server_blob,
+ &shared_secret);
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ if (r !=0 )
+ goto out;
+
+ /* calc and verify H */
+ hashlen = sizeof(hash);
+ if ((r = kex_gen_hash(
+ kex->hash_alg,
+ kex->client_version,
+ kex->server_version,
+ kex->my,
+ kex->peer,
+ server_host_key_blob,
+ kex->client_pub,
+ server_blob,
+ shared_secret,
+ hash, &hashlen)) != 0)
+ goto out;
+
+ if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
+ kex->hostkey_alg, ssh->compat)) != 0)
+ goto out;
+
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
+ r = kex_send_newkeys(ssh);
+out:
+ explicit_bzero(hash, sizeof(hash));
+ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
+ explicit_bzero(kex->sntrup4591761_client_key,
+ sizeof(kex->sntrup4591761_client_key));
+ sshbuf_free(server_host_key_blob);
+ free(signature);
+ sshbuf_free(tmp);
+ sshkey_free(server_host_key);
+ sshbuf_free(server_blob);
+ sshbuf_free(shared_secret);
+ sshbuf_free(kex->client_pub);
+ kex->client_pub = NULL;
+ return r;
+}
+
+int
+kex_gen_server(struct ssh *ssh)
+{
+ debug("expecting SSH2_MSG_KEX_ECDH_INIT");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &input_kex_gen_init);
+ return 0;
+}
+
+static int
+input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
+{
+ struct kex *kex = ssh->kex;
+ struct sshkey *server_host_private, *server_host_public;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *server_pubkey = NULL;
+ struct sshbuf *client_pubkey = NULL;
+ struct sshbuf *server_host_key_blob = NULL;
+ u_char *signature = NULL, hash[SSH_DIGEST_MAX_LENGTH];
+ size_t slen, hashlen;
+ int r;
+
+ if ((r = kex_load_hostkey(ssh, &server_host_private,
+ &server_host_public)) != 0)
+ goto out;
+
+ if ((r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ goto out;
+
+ /* compute shared secret */
+ switch (kex->kex_type) {
+#ifdef WITH_OPENSSL
+ case KEX_DH_GRP1_SHA1:
+ case KEX_DH_GRP14_SHA1:
+ case KEX_DH_GRP14_SHA256:
+ case KEX_DH_GRP16_SHA512:
+ case KEX_DH_GRP18_SHA512:
+ r = kex_dh_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ break;
+ case KEX_ECDH_SHA2:
+ r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ break;
+#endif
+ case KEX_C25519_SHA256:
+ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
+ &shared_secret);
+ break;
+ case KEX_KEM_SNTRUP4591761X25519_SHA512:
+ r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey,
+ &server_pubkey, &shared_secret);
+ break;
+ default:
+ r = SSH_ERR_INVALID_ARGUMENT;
+ break;
+ }
+ if (r !=0 )
+ goto out;
+
+ /* calc H */
+ if ((server_host_key_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
+ goto out;
+ hashlen = sizeof(hash);
+ if ((r = kex_gen_hash(
+ kex->hash_alg,
+ kex->client_version,
+ kex->server_version,
+ kex->peer,
+ kex->my,
+ server_host_key_blob,
+ client_pubkey,
+ server_pubkey,
+ shared_secret,
+ hash, &hashlen)) != 0)
+ goto out;
+
+ /* sign H */
+ if ((r = kex->sign(ssh, server_host_private, server_host_public,
+ &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0)
+ goto out;
+
+ /* send server hostkey, ECDH pubkey 'Q_S' and signed H */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_REPLY)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 ||
+ (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ goto out;
+
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
+ r = kex_send_newkeys(ssh);
+out:
+ explicit_bzero(hash, sizeof(hash));
+ sshbuf_free(server_host_key_blob);
+ free(signature);
+ sshbuf_free(shared_secret);
+ sshbuf_free(client_pubkey);
+ sshbuf_free(server_pubkey);
+ return r;
+}
diff --git a/kexgex.c b/kexgex.c
index 3ca4bd37000b..8040a13202fc 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -1,104 +1,104 @@
-/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */
+/* $OpenBSD: kexgex.c,v 1.32 2019/01/23 00:30:41 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <openssl/evp.h>
#include <signal.h>
#include "openbsd-compat/openssl-compat.h"
#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "ssh2.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "digest.h"
int
kexgex_hash(
int hash_alg,
- const char *client_version_string,
- const char *server_version_string,
- const u_char *ckexinit, size_t ckexinitlen,
- const u_char *skexinit, size_t skexinitlen,
- const u_char *serverhostkeyblob, size_t sbloblen,
+ const struct sshbuf *client_version,
+ const struct sshbuf *server_version,
+ const struct sshbuf *client_kexinit,
+ const struct sshbuf *server_kexinit,
+ const struct sshbuf *server_host_key_blob,
int min, int wantbits, int max,
const BIGNUM *prime,
const BIGNUM *gen,
const BIGNUM *client_dh_pub,
const BIGNUM *server_dh_pub,
- const BIGNUM *shared_secret,
+ const u_char *shared_secret, size_t secretlen,
u_char *hash, size_t *hashlen)
{
struct sshbuf *b;
int r;
if (*hashlen < ssh_digest_bytes(SSH_DIGEST_SHA1))
return SSH_ERR_INVALID_ARGUMENT;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
+ if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
+ (r = sshbuf_put_stringb(b, server_version)) < 0 ||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
- (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
+ (r = sshbuf_put_u32(b, sshbuf_len(client_kexinit) + 1)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, ckexinit, ckexinitlen)) != 0 ||
- (r = sshbuf_put_u32(b, skexinitlen+1)) != 0 ||
+ (r = sshbuf_putb(b, client_kexinit)) != 0 ||
+ (r = sshbuf_put_u32(b, sshbuf_len(server_kexinit) + 1)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
- (r = sshbuf_put(b, skexinit, skexinitlen)) != 0 ||
- (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) != 0 ||
+ (r = sshbuf_putb(b, server_kexinit)) != 0 ||
+ (r = sshbuf_put_stringb(b, server_host_key_blob)) != 0 ||
(min != -1 && (r = sshbuf_put_u32(b, min)) != 0) ||
(r = sshbuf_put_u32(b, wantbits)) != 0 ||
(max != -1 && (r = sshbuf_put_u32(b, max)) != 0) ||
(r = sshbuf_put_bignum2(b, prime)) != 0 ||
(r = sshbuf_put_bignum2(b, gen)) != 0 ||
(r = sshbuf_put_bignum2(b, client_dh_pub)) != 0 ||
(r = sshbuf_put_bignum2(b, server_dh_pub)) != 0 ||
- (r = sshbuf_put_bignum2(b, shared_secret)) != 0) {
+ (r = sshbuf_put(b, shared_secret, secretlen)) != 0) {
sshbuf_free(b);
return r;
}
#ifdef DEBUG_KEXDH
sshbuf_dump(b, stderr);
#endif
if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) {
sshbuf_free(b);
return SSH_ERR_LIBCRYPTO_ERROR;
}
sshbuf_free(b);
*hashlen = ssh_digest_bytes(hash_alg);
#ifdef DEBUG_KEXDH
dump_digest("hash", hash, *hashlen);
#endif
return 0;
}
#endif /* WITH_OPENSSL */
diff --git a/kexgexc.c b/kexgexc.c
index 0d07f73c794c..1c65b8a18016 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,270 +1,219 @@
-/* $OpenBSD: kexgexc.c,v 1.27 2018/02/07 02:06:51 jsing Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.34 2019/01/23 00:30:41 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <openssl/dh.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "openbsd-compat/openssl-compat.h"
#include "sshkey.h"
#include "cipher.h"
#include "digest.h"
#include "kex.h"
#include "log.h"
#include "packet.h"
#include "dh.h"
#include "ssh2.h"
#include "compat.h"
#include "dispatch.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "misc.h"
static int input_kex_dh_gex_group(int, u_int32_t, struct ssh *);
static int input_kex_dh_gex_reply(int, u_int32_t, struct ssh *);
int
kexgex_client(struct ssh *ssh)
{
struct kex *kex = ssh->kex;
int r;
u_int nbits;
nbits = dh_estimate(kex->dh_need * 8);
kex->min = DH_GRP_MIN;
kex->max = DH_GRP_MAX;
kex->nbits = nbits;
if (datafellows & SSH_BUG_DHGEX_LARGE)
kex->nbits = MINIMUM(kex->nbits, 4096);
/* New GEX request */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 ||
(r = sshpkt_put_u32(ssh, kex->min)) != 0 ||
(r = sshpkt_put_u32(ssh, kex->nbits)) != 0 ||
(r = sshpkt_put_u32(ssh, kex->max)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent",
kex->min, kex->nbits, kex->max);
#ifdef DEBUG_KEXDH
fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
kex->min, kex->nbits, kex->max);
#endif
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP,
&input_kex_dh_gex_group);
r = 0;
out:
return r;
}
static int
input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
BIGNUM *p = NULL, *g = NULL;
const BIGNUM *pub_key;
int r, bits;
debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
- if ((p = BN_new()) == NULL ||
- (g = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_bignum2(ssh, p)) != 0 ||
- (r = sshpkt_get_bignum2(ssh, g)) != 0 ||
+ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
+ (r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
if ((bits = BN_num_bits(p)) < 0 ||
(u_int)bits < kex->min || (u_int)bits > kex->max) {
r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
goto out;
}
if ((kex->dh = dh_new_group(g, p)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
p = g = NULL; /* belong to kex->dh now */
/* generate and send 'e', client DH public key */
if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
goto out;
DH_get0_key(kex->dh, &pub_key, NULL);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
(r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
#ifdef DEBUG_KEXDH
DHparams_print_fp(stderr, kex->dh);
fprintf(stderr, "pub= ");
BN_print_fp(stderr, pub_key);
fprintf(stderr, "\n");
#endif
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
r = 0;
out:
BN_clear_free(p);
BN_clear_free(g);
return r;
}
static int
input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
- BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
+ BIGNUM *dh_server_pub = NULL;
const BIGNUM *pub_key, *dh_p, *dh_g;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *tmp = NULL, *server_host_key_blob = NULL;
struct sshkey *server_host_key = NULL;
- u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+ u_char *signature = NULL;
u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t klen = 0, slen, sbloblen, hashlen;
- int kout, r;
+ size_t slen, hashlen;
+ int r;
debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
- if (kex->verify_host_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
/* key, cert */
- if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
- &sbloblen)) != 0 ||
- (r = sshkey_from_blob(server_host_key_blob, sbloblen,
- &server_host_key)) != 0)
+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
goto out;
- if (server_host_key->type != kex->hostkey_type ||
- (kex->hostkey_type == KEY_ECDSA &&
- server_host_key->ecdsa_nid != kex->hostkey_nid)) {
- r = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
- }
- if (kex->verify_host_key(server_host_key, ssh) == -1) {
- r = SSH_ERR_SIGNATURE_INVALID;
- goto out;
- }
- /* DH parameter f, server public DH key */
- if ((dh_server_pub = BN_new()) == NULL) {
+ /* sshkey_fromb() consumes its buffer, so make a copy */
+ if ((tmp = sshbuf_fromb(server_host_key_blob)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- /* signed H */
- if ((r = sshpkt_get_bignum2(ssh, dh_server_pub)) != 0 ||
+ if ((r = sshkey_fromb(tmp, &server_host_key)) != 0 ||
+ (r = kex_verify_host_key(ssh, server_host_key)) != 0)
+ goto out;
+ /* DH parameter f, server public DH key, signed H */
+ if ((r = sshpkt_get_bignum2(ssh, &dh_server_pub)) != 0 ||
(r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_server_pub= ");
- BN_print_fp(stderr, dh_server_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_server_pub)) {
- sshpkt_disconnect(ssh, "bad server public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
+ if ((shared_secret = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((kout = DH_compute_key(kbuf, dh_server_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
goto out;
- }
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
if (ssh->compat & SSH_OLD_DHGEX)
kex->min = kex->max = -1;
/* calc and verify H */
DH_get0_key(kex->dh, &pub_key, NULL);
DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
hashlen = sizeof(hash);
if ((r = kexgex_hash(
kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- server_host_key_blob, sbloblen,
+ kex->client_version,
+ kex->server_version,
+ kex->my,
+ kex->peer,
+ server_host_key_blob,
kex->min, kex->nbits, kex->max,
dh_p, dh_g,
pub_key,
dh_server_pub,
- shared_secret,
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
hash, &hashlen)) != 0)
goto out;
if ((r = sshkey_verify(server_host_key, signature, slen, hash,
hashlen, kex->hostkey_alg, ssh->compat)) != 0)
goto out;
- /* save session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
r = kex_send_newkeys(ssh);
out:
explicit_bzero(hash, sizeof(hash));
DH_free(kex->dh);
kex->dh = NULL;
BN_clear_free(dh_server_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- BN_clear_free(shared_secret);
+ sshbuf_free(shared_secret);
sshkey_free(server_host_key);
- free(server_host_key_blob);
+ sshbuf_free(tmp);
+ sshbuf_free(server_host_key_blob);
free(signature);
return r;
}
#endif /* WITH_OPENSSL */
diff --git a/kexgexs.c b/kexgexs.c
index dc9c0bc6024d..8ee3aaccb992 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,256 +1,204 @@
-/* $OpenBSD: kexgexs.c,v 1.35 2018/10/04 00:04:41 djm Exp $ */
+/* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <openssl/dh.h>
#include "openbsd-compat/openssl-compat.h"
#include "sshkey.h"
#include "cipher.h"
#include "digest.h"
#include "kex.h"
#include "log.h"
#include "packet.h"
#include "dh.h"
#include "ssh2.h"
#include "compat.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "dispatch.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "misc.h"
static int input_kex_dh_gex_request(int, u_int32_t, struct ssh *);
static int input_kex_dh_gex_init(int, u_int32_t, struct ssh *);
int
kexgex_server(struct ssh *ssh)
{
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST,
&input_kex_dh_gex_request);
debug("expecting SSH2_MSG_KEX_DH_GEX_REQUEST");
return 0;
}
static int
input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
int r;
u_int min = 0, max = 0, nbits = 0;
const BIGNUM *dh_p, *dh_g;
debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
(r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
(r = sshpkt_get_u32(ssh, &max)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
kex->nbits = nbits;
kex->min = min;
kex->max = max;
min = MAXIMUM(DH_GRP_MIN, min);
max = MINIMUM(DH_GRP_MAX, max);
nbits = MAXIMUM(DH_GRP_MIN, nbits);
nbits = MINIMUM(DH_GRP_MAX, nbits);
if (kex->max < kex->min || kex->nbits < kex->min ||
kex->max < kex->nbits || kex->max < DH_GRP_MIN) {
r = SSH_ERR_DH_GEX_OUT_OF_RANGE;
goto out;
}
/* Contact privileged parent */
kex->dh = PRIVSEP(choose_dh(min, nbits, max));
if (kex->dh == NULL) {
sshpkt_disconnect(ssh, "no matching DH grp found");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||
(r = sshpkt_put_bignum2(ssh, dh_p)) != 0 ||
(r = sshpkt_put_bignum2(ssh, dh_g)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
/* Compute our exchange value in parallel with the client */
if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
goto out;
debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init);
r = 0;
out:
return r;
}
static int
input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
{
struct kex *kex = ssh->kex;
- BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
+ BIGNUM *dh_client_pub = NULL;
const BIGNUM *pub_key, *dh_p, *dh_g;
+ struct sshbuf *shared_secret = NULL;
+ struct sshbuf *server_host_key_blob = NULL;
struct sshkey *server_host_public, *server_host_private;
- u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL;
+ u_char *signature = NULL;
u_char hash[SSH_DIGEST_MAX_LENGTH];
- size_t sbloblen, slen;
- size_t klen = 0, hashlen;
- int kout, r;
+ size_t slen, hashlen;
+ int r;
- if (kex->load_host_public_key == NULL ||
- kex->load_host_private_key == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- server_host_public = kex->load_host_public_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- server_host_private = kex->load_host_private_key(kex->hostkey_type,
- kex->hostkey_nid, ssh);
- if (server_host_public == NULL) {
- r = SSH_ERR_NO_HOSTKEY_LOADED;
+ if ((r = kex_load_hostkey(ssh, &server_host_private,
+ &server_host_public)) != 0)
goto out;
- }
/* key, cert */
- if ((dh_client_pub = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 ||
+ if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
-
- DH_get0_key(kex->dh, &pub_key, NULL);
- DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
-
-#ifdef DEBUG_KEXDH
- fprintf(stderr, "dh_client_pub= ");
- BN_print_fp(stderr, dh_client_pub);
- fprintf(stderr, "\n");
- debug("bits %d", BN_num_bits(dh_client_pub));
- DHparams_print_fp(stderr, kex->dh);
- fprintf(stderr, "pub= ");
- BN_print_fp(stderr, pub_key);
- fprintf(stderr, "\n");
-#endif
- if (!dh_pub_is_valid(kex->dh, dh_client_pub)) {
- sshpkt_disconnect(ssh, "bad client public DH value");
- r = SSH_ERR_MESSAGE_INCOMPLETE;
- goto out;
- }
-
- klen = DH_size(kex->dh);
- if ((kbuf = malloc(klen)) == NULL ||
- (shared_secret = BN_new()) == NULL) {
+ if ((shared_secret = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 ||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0)
+ goto out;
+ if ((server_host_key_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
goto out;
}
-#ifdef DEBUG_KEXDH
- dump_digest("shared secret", kbuf, kout);
-#endif
- if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob,
- &sbloblen)) != 0)
+ if ((r = sshkey_putb(server_host_public, server_host_key_blob)) != 0)
goto out;
+
/* calc H */
+ DH_get0_key(kex->dh, &pub_key, NULL);
+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
hashlen = sizeof(hash);
if ((r = kexgex_hash(
kex->hash_alg,
- kex->client_version_string,
- kex->server_version_string,
- sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
- sshbuf_ptr(kex->my), sshbuf_len(kex->my),
- server_host_key_blob, sbloblen,
+ kex->client_version,
+ kex->server_version,
+ kex->peer,
+ kex->my,
+ server_host_key_blob,
kex->min, kex->nbits, kex->max,
dh_p, dh_g,
dh_client_pub,
pub_key,
- shared_secret,
+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
hash, &hashlen)) != 0)
goto out;
- /* save session id := H */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- memcpy(kex->session_id, hash, kex->session_id_len);
- }
-
/* sign H */
- if ((r = kex->sign(server_host_private, server_host_public, &signature,
- &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0)
+ if ((r = kex->sign(ssh, server_host_private, server_host_public,
+ &signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0)
goto out;
- /* destroy_sensitive_data(); */
-
/* send server hostkey, DH pubkey 'f' and signed H */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
- (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, server_host_key_blob)) != 0 ||
(r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */
(r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
- if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
r = kex_send_newkeys(ssh);
out:
explicit_bzero(hash, sizeof(hash));
DH_free(kex->dh);
kex->dh = NULL;
BN_clear_free(dh_client_pub);
- if (kbuf) {
- explicit_bzero(kbuf, klen);
- free(kbuf);
- }
- BN_clear_free(shared_secret);
- free(server_host_key_blob);
+ sshbuf_free(shared_secret);
+ sshbuf_free(server_host_key_blob);
free(signature);
return r;
}
#endif /* WITH_OPENSSL */
diff --git a/kexsntrup4591761x25519.c b/kexsntrup4591761x25519.c
new file mode 100644
index 000000000000..3b9b664f8b1f
--- /dev/null
+++ b/kexsntrup4591761x25519.c
@@ -0,0 +1,219 @@
+/* $OpenBSD: kexsntrup4591761x25519.c,v 1.3 2019/01/21 10:40:11 djm Exp $ */
+/*
+ * Copyright (c) 2019 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "sshkey.h"
+#include "kex.h"
+#include "sshbuf.h"
+#include "digest.h"
+#include "ssherr.h"
+
+int
+kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
+{
+ struct sshbuf *buf = NULL;
+ u_char *cp = NULL;
+ size_t need;
+ int r;
+
+ if ((buf = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
+ if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
+ goto out;
+ crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key sntrup4591761:", cp,
+ crypto_kem_sntrup4591761_PUBLICKEYBYTES);
+#endif
+ cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
+ kexc25519_keygen(kex->c25519_client_key, cp);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
+#endif
+ kex->client_pub = buf;
+ buf = NULL;
+ out:
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_kem_sntrup4591761x25519_enc(struct kex *kex,
+ const struct sshbuf *client_blob, struct sshbuf **server_blobp,
+ struct sshbuf **shared_secretp)
+{
+ struct sshbuf *server_blob = NULL;
+ struct sshbuf *buf = NULL;
+ const u_char *client_pub;
+ u_char *kem_key, *ciphertext, *server_pub;
+ u_char server_key[CURVE25519_SIZE];
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t need;
+ int r;
+
+ *server_blobp = NULL;
+ *shared_secretp = NULL;
+
+ /* client_blob contains both KEM and ECDH client pubkeys */
+ need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
+ if (sshbuf_len(client_blob) != need) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ client_pub = sshbuf_ptr(client_blob);
+#ifdef DEBUG_KEXECDH
+ dump_digest("client public key sntrup4591761:", client_pub,
+ crypto_kem_sntrup4591761_PUBLICKEYBYTES);
+ dump_digest("client public key 25519:",
+ client_pub + crypto_kem_sntrup4591761_PUBLICKEYBYTES,
+ CURVE25519_SIZE);
+#endif
+ /* allocate buffer for concatenation of KEM key and ECDH shared key */
+ /* the buffer will be hashed and the result is the shared secret */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
+ &kem_key)) != 0)
+ goto out;
+ /* allocate space for encrypted KEM key and ECDH pub key */
+ if ((server_blob = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
+ goto out;
+ /* generate and encrypt KEM key with client key */
+ crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub);
+ /* generate ECDH key pair, store server pubkey after ciphertext */
+ server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
+ kexc25519_keygen(server_key, server_pub);
+ /* append ECDH shared key */
+ client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
+ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
+ goto out;
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
+ dump_digest("server cipher text:", ciphertext,
+ crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
+ dump_digest("server kem key:", kem_key, sizeof(kem_key));
+ dump_digest("concatenation of KEM key and ECDH shared key:",
+ sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ /* string-encoded hash is resulting shared secret */
+ sshbuf_reset(buf);
+ if ((r = sshbuf_put_string(buf, hash,
+ ssh_digest_bytes(kex->hash_alg))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ *server_blobp = server_blob;
+ *shared_secretp = buf;
+ server_blob = NULL;
+ buf = NULL;
+ out:
+ explicit_bzero(hash, sizeof(hash));
+ explicit_bzero(server_key, sizeof(server_key));
+ sshbuf_free(server_blob);
+ sshbuf_free(buf);
+ return r;
+}
+
+int
+kex_kem_sntrup4591761x25519_dec(struct kex *kex,
+ const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
+{
+ struct sshbuf *buf = NULL;
+ u_char *kem_key = NULL;
+ const u_char *ciphertext, *server_pub;
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
+ size_t need;
+ int r, decoded;
+
+ *shared_secretp = NULL;
+
+ need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ if (sshbuf_len(server_blob) != need) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ ciphertext = sshbuf_ptr(server_blob);
+ server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
+#ifdef DEBUG_KEXECDH
+ dump_digest("server cipher text:", ciphertext,
+ crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
+ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
+#endif
+ /* hash concatenation of KEM key and ECDH shared key */
+ if ((buf = sshbuf_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
+ &kem_key)) != 0)
+ goto out;
+ decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext,
+ kex->sntrup4591761_client_key);
+ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
+ buf, 1)) < 0)
+ goto out;
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("client kem key:", kem_key, sizeof(kem_key));
+ dump_digest("concatenation of KEM key and ECDH shared key:",
+ sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ sshbuf_reset(buf);
+ if ((r = sshbuf_put_string(buf, hash,
+ ssh_digest_bytes(kex->hash_alg))) != 0)
+ goto out;
+#ifdef DEBUG_KEXECDH
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
+#endif
+ if (decoded != 0) {
+ r = SSH_ERR_SIGNATURE_INVALID;
+ goto out;
+ }
+ *shared_secretp = buf;
+ buf = NULL;
+ out:
+ explicit_bzero(hash, sizeof(hash));
+ sshbuf_free(buf);
+ return r;
+}
diff --git a/loginrec.c b/loginrec.c
index 9a427dec4125..5f2a47797be9 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -1,1724 +1,1724 @@
/*
* Copyright (c) 2000 Andre Lucas. All rights reserved.
* Portions copyright (c) 1998 Todd C. Miller
* Portions copyright (c) 1996 Jason Downs
* Portions copyright (c) 1996 Theo de Raadt
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The btmp logging code is derived from login.c from util-linux and is under
* the the following license:
*
* Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
** loginrec.c: platform-independent login recording and lastlog retrieval
**/
/*
* The new login code explained
* ============================
*
* This code attempts to provide a common interface to login recording
* (utmp and friends) and last login time retrieval.
*
* Its primary means of achieving this is to use 'struct logininfo', a
* union of all the useful fields in the various different types of
* system login record structures one finds on UNIX variants.
*
* We depend on autoconf to define which recording methods are to be
* used, and which fields are contained in the relevant data structures
* on the local system. Many C preprocessor symbols affect which code
* gets compiled here.
*
* The code is designed to make it easy to modify a particular
* recording method, without affecting other methods nor requiring so
* many nested conditional compilation blocks as were commonplace in
* the old code.
*
* For login recording, we try to use the local system's libraries as
* these are clearly most likely to work correctly. For utmp systems
* this usually means login() and logout() or setutent() etc., probably
* in libutil, along with logwtmp() etc. On these systems, we fall back
* to writing the files directly if we have to, though this method
* requires very thorough testing so we do not corrupt local auditing
* information. These files and their access methods are very system
* specific indeed.
*
* For utmpx systems, the corresponding library functions are
* setutxent() etc. To the author's knowledge, all utmpx systems have
* these library functions and so no direct write is attempted. If such
* a system exists and needs support, direct analogues of the [uw]tmp
* code should suffice.
*
* Retrieving the time of last login ('lastlog') is in some ways even
* more problemmatic than login recording. Some systems provide a
* simple table of all users which we seek based on uid and retrieve a
* relatively standard structure. Others record the same information in
* a directory with a separate file, and others don't record the
* information separately at all. For systems in the latter category,
* we look backwards in the wtmp or wtmpx file for the last login entry
* for our user. Naturally this is slower and on busy systems could
* incur a significant performance penalty.
*
* Calling the new code
* --------------------
*
* In OpenSSH all login recording and retrieval is performed in
* login.c. Here you'll find working examples. Also, in the logintest.c
* program there are more examples.
*
* Internal handler calling method
* -------------------------------
*
* When a call is made to login_login() or login_logout(), both
* routines set a struct logininfo flag defining which action (log in,
* or log out) is to be taken. They both then call login_write(), which
* calls whichever of the many structure-specific handlers autoconf
* selects for the local system.
*
* The handlers themselves handle system data structure specifics. Both
* struct utmp and struct utmpx have utility functions (see
* construct_utmp*()) to try to make it simpler to add extra systems
* that introduce new features to either structure.
*
* While it may seem terribly wasteful to replicate so much similar
* code for each method, experience has shown that maintaining code to
* write both struct utmp and utmpx in one function, whilst maintaining
* support for all systems whether they have library support or not, is
* a difficult and time-consuming task.
*
* Lastlog support proceeds similarly. Functions login_get_lastlog()
* (and its OpenSSH-tuned friend login_get_lastlog_time()) call
* getlast_entry(), which tries one of three methods to find the last
* login time. It uses local system lastlog support if it can,
* otherwise it tries wtmp or wtmpx before giving up and returning 0,
* meaning "tilt".
*
* Maintenance
* -----------
*
* In many cases it's possible to tweak autoconf to select the correct
* methods for a particular platform, either by improving the detection
* code (best), or by presetting DISABLE_<method> or CONF_<method>_FILE
* symbols for the platform.
*
* Use logintest to check which symbols are defined before modifying
* configure.ac and loginrec.c. (You have to build logintest yourself
* with 'make logintest' as it's not built by default.)
*
* Otherwise, patches to the specific method(s) are very helpful!
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <pwd.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "xmalloc.h"
#include "sshkey.h"
#include "hostfile.h"
#include "ssh.h"
#include "loginrec.h"
#include "log.h"
#include "atomicio.h"
#include "packet.h"
#include "canohost.h"
#include "auth.h"
#include "sshbuf.h"
#include "ssherr.h"
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
/**
** prototypes for helper functions in this file
**/
#if HAVE_UTMP_H
void set_utmp_time(struct logininfo *li, struct utmp *ut);
void construct_utmp(struct logininfo *li, struct utmp *ut);
#endif
#ifdef HAVE_UTMPX_H
void set_utmpx_time(struct logininfo *li, struct utmpx *ut);
void construct_utmpx(struct logininfo *li, struct utmpx *ut);
#endif
int utmp_write_entry(struct logininfo *li);
int utmpx_write_entry(struct logininfo *li);
int wtmp_write_entry(struct logininfo *li);
int wtmpx_write_entry(struct logininfo *li);
int lastlog_write_entry(struct logininfo *li);
int syslogin_write_entry(struct logininfo *li);
int getlast_entry(struct logininfo *li);
int lastlog_get_entry(struct logininfo *li);
int utmpx_get_entry(struct logininfo *li);
int wtmp_get_entry(struct logininfo *li);
int wtmpx_get_entry(struct logininfo *li);
extern struct sshbuf *loginmsg;
/* pick the shortest string */
#define MIN_SIZEOF(s1,s2) (sizeof(s1) < sizeof(s2) ? sizeof(s1) : sizeof(s2))
/**
** platform-independent login functions
**/
/*
* login_login(struct logininfo *) - Record a login
*
* Call with a pointer to a struct logininfo initialised with
* login_init_entry() or login_alloc_entry()
*
* Returns:
* >0 if successful
* 0 on failure (will use OpenSSH's logging facilities for diagnostics)
*/
int
login_login(struct logininfo *li)
{
li->type = LTYPE_LOGIN;
return (login_write(li));
}
/*
* login_logout(struct logininfo *) - Record a logout
*
* Call as with login_login()
*
* Returns:
* >0 if successful
* 0 on failure (will use OpenSSH's logging facilities for diagnostics)
*/
int
login_logout(struct logininfo *li)
{
li->type = LTYPE_LOGOUT;
return (login_write(li));
}
/*
* login_get_lastlog_time(int) - Retrieve the last login time
*
* Retrieve the last login time for the given uid. Will try to use the
* system lastlog facilities if they are available, but will fall back
* to looking in wtmp/wtmpx if necessary
*
* Returns:
* 0 on failure, or if user has never logged in
* Time in seconds from the epoch if successful
*
* Useful preprocessor symbols:
* DISABLE_LASTLOG: If set, *never* even try to retrieve lastlog
* info
* USE_LASTLOG: If set, indicates the presence of system lastlog
* facilities. If this and DISABLE_LASTLOG are not set,
* try to retrieve lastlog information from wtmp/wtmpx.
*/
unsigned int
login_get_lastlog_time(const uid_t uid)
{
struct logininfo li;
if (login_get_lastlog(&li, uid))
return (li.tv_sec);
else
return (0);
}
/*
* login_get_lastlog(struct logininfo *, int) - Retrieve a lastlog entry
*
* Retrieve a logininfo structure populated (only partially) with
* information from the system lastlog data, or from wtmp/wtmpx if no
* system lastlog information exists.
*
* Note this routine must be given a pre-allocated logininfo.
*
* Returns:
* >0: A pointer to your struct logininfo if successful
* 0 on failure (will use OpenSSH's logging facilities for diagnostics)
*/
struct logininfo *
login_get_lastlog(struct logininfo *li, const uid_t uid)
{
struct passwd *pw;
memset(li, '\0', sizeof(*li));
li->uid = uid;
/*
* If we don't have a 'real' lastlog, we need the username to
* reliably search wtmp(x) for the last login (see
* wtmp_get_entry().)
*/
pw = getpwuid(uid);
if (pw == NULL)
fatal("%s: Cannot find account for uid %ld", __func__,
(long)uid);
if (strlcpy(li->username, pw->pw_name, sizeof(li->username)) >=
sizeof(li->username)) {
error("%s: username too long (%lu > max %lu)", __func__,
(unsigned long)strlen(pw->pw_name),
(unsigned long)sizeof(li->username) - 1);
return NULL;
}
if (getlast_entry(li))
return (li);
else
return (NULL);
}
/*
* login_alloc_entry(int, char*, char*, char*) - Allocate and initialise
* a logininfo structure
*
* This function creates a new struct logininfo, a data structure
* meant to carry the information required to portably record login info.
*
* Returns a pointer to a newly created struct logininfo. If memory
* allocation fails, the program halts.
*/
struct
logininfo *login_alloc_entry(pid_t pid, const char *username,
const char *hostname, const char *line)
{
struct logininfo *newli;
newli = xmalloc(sizeof(*newli));
login_init_entry(newli, pid, username, hostname, line);
return (newli);
}
/* login_free_entry(struct logininfo *) - free struct memory */
void
login_free_entry(struct logininfo *li)
{
free(li);
}
/* login_init_entry(struct logininfo *, int, char*, char*, char*)
* - initialise a struct logininfo
*
* Populates a new struct logininfo, a data structure meant to carry
* the information required to portably record login info.
*
* Returns: 1
*/
int
login_init_entry(struct logininfo *li, pid_t pid, const char *username,
const char *hostname, const char *line)
{
struct passwd *pw;
memset(li, 0, sizeof(*li));
li->pid = pid;
/* set the line information */
if (line)
line_fullname(li->line, line, sizeof(li->line));
if (username) {
strlcpy(li->username, username, sizeof(li->username));
pw = getpwnam(li->username);
if (pw == NULL) {
fatal("%s: Cannot find user \"%s\"", __func__,
li->username);
}
li->uid = pw->pw_uid;
}
if (hostname)
strlcpy(li->hostname, hostname, sizeof(li->hostname));
return (1);
}
/*
* login_set_current_time(struct logininfo *) - set the current time
*
* Set the current time in a logininfo structure. This function is
* meant to eliminate the need to deal with system dependencies for
* time handling.
*/
void
login_set_current_time(struct logininfo *li)
{
struct timeval tv;
gettimeofday(&tv, NULL);
li->tv_sec = tv.tv_sec;
li->tv_usec = tv.tv_usec;
}
/* copy a sockaddr_* into our logininfo */
void
login_set_addr(struct logininfo *li, const struct sockaddr *sa,
const unsigned int sa_size)
{
unsigned int bufsize = sa_size;
/* make sure we don't overrun our union */
if (sizeof(li->hostaddr) < sa_size)
bufsize = sizeof(li->hostaddr);
memcpy(&li->hostaddr.sa, sa, bufsize);
}
/**
** login_write: Call low-level recording functions based on autoconf
** results
**/
int
login_write(struct logininfo *li)
{
#ifndef HAVE_CYGWIN
if (geteuid() != 0) {
logit("Attempt to write login records by non-root user (aborting)");
return (1);
}
#endif
/* set the timestamp */
login_set_current_time(li);
#ifdef USE_LOGIN
syslogin_write_entry(li);
#endif
#ifdef USE_LASTLOG
if (li->type == LTYPE_LOGIN)
lastlog_write_entry(li);
#endif
#ifdef USE_UTMP
utmp_write_entry(li);
#endif
#ifdef USE_WTMP
wtmp_write_entry(li);
#endif
#ifdef USE_UTMPX
utmpx_write_entry(li);
#endif
#ifdef USE_WTMPX
wtmpx_write_entry(li);
#endif
#ifdef CUSTOM_SYS_AUTH_RECORD_LOGIN
if (li->type == LTYPE_LOGIN &&
!sys_auth_record_login(li->username,li->hostname,li->line,
- &loginmsg))
+ loginmsg))
logit("Writing login record failed for %s", li->username);
#endif
#ifdef SSH_AUDIT_EVENTS
if (li->type == LTYPE_LOGIN)
audit_session_open(li);
else if (li->type == LTYPE_LOGOUT)
audit_session_close(li);
#endif
return (0);
}
#ifdef LOGIN_NEEDS_UTMPX
int
login_utmp_only(struct logininfo *li)
{
li->type = LTYPE_LOGIN;
login_set_current_time(li);
# ifdef USE_UTMP
utmp_write_entry(li);
# endif
# ifdef USE_WTMP
wtmp_write_entry(li);
# endif
# ifdef USE_UTMPX
utmpx_write_entry(li);
# endif
# ifdef USE_WTMPX
wtmpx_write_entry(li);
# endif
return (0);
}
#endif
/**
** getlast_entry: Call low-level functions to retrieve the last login
** time.
**/
/* take the uid in li and return the last login time */
int
getlast_entry(struct logininfo *li)
{
#ifdef USE_LASTLOG
return(lastlog_get_entry(li));
#else /* !USE_LASTLOG */
#if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \
defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER)
return (utmpx_get_entry(li));
#endif
#if defined(DISABLE_LASTLOG)
/* On some systems we shouldn't even try to obtain last login
* time, e.g. AIX */
return (0);
# elif defined(USE_WTMP) && \
(defined(HAVE_TIME_IN_UTMP) || defined(HAVE_TV_IN_UTMP))
/* retrieve last login time from utmp */
return (wtmp_get_entry(li));
# elif defined(USE_WTMPX) && \
(defined(HAVE_TIME_IN_UTMPX) || defined(HAVE_TV_IN_UTMPX))
/* If wtmp isn't available, try wtmpx */
return (wtmpx_get_entry(li));
# else
/* Give up: No means of retrieving last login time */
return (0);
# endif /* DISABLE_LASTLOG */
#endif /* USE_LASTLOG */
}
/*
* 'line' string utility functions
*
* These functions process the 'line' string into one of three forms:
*
* 1. The full filename (including '/dev')
* 2. The stripped name (excluding '/dev')
* 3. The abbreviated name (e.g. /dev/ttyp00 -> yp00
* /dev/pts/1 -> ts/1 )
*
* Form 3 is used on some systems to identify a .tmp.? entry when
* attempting to remove it. Typically both addition and removal is
* performed by one application - say, sshd - so as long as the choice
* uniquely identifies a terminal it's ok.
*/
/*
* line_fullname(): add the leading '/dev/' if it doesn't exist make
* sure dst has enough space, if not just copy src (ugh)
*/
char *
line_fullname(char *dst, const char *src, u_int dstsize)
{
memset(dst, '\0', dstsize);
if ((strncmp(src, "/dev/", 5) == 0) || (dstsize < (strlen(src) + 5)))
strlcpy(dst, src, dstsize);
else {
strlcpy(dst, "/dev/", dstsize);
strlcat(dst, src, dstsize);
}
return (dst);
}
/* line_stripname(): strip the leading '/dev' if it exists, return dst */
char *
line_stripname(char *dst, const char *src, int dstsize)
{
memset(dst, '\0', dstsize);
if (strncmp(src, "/dev/", 5) == 0)
strlcpy(dst, src + 5, dstsize);
else
strlcpy(dst, src, dstsize);
return (dst);
}
/*
* line_abbrevname(): Return the abbreviated (usually four-character)
* form of the line (Just use the last <dstsize> characters of the
* full name.)
*
* NOTE: use strncpy because we do NOT necessarily want zero
* termination
*/
char *
line_abbrevname(char *dst, const char *src, int dstsize)
{
size_t len;
memset(dst, '\0', dstsize);
/* Always skip prefix if present */
if (strncmp(src, "/dev/", 5) == 0)
src += 5;
#ifdef WITH_ABBREV_NO_TTY
if (strncmp(src, "tty", 3) == 0)
src += 3;
#endif
len = strlen(src);
if (len > 0) {
if (((int)len - dstsize) > 0)
src += ((int)len - dstsize);
/* note: _don't_ change this to strlcpy */
strncpy(dst, src, (size_t)dstsize);
}
return (dst);
}
/**
** utmp utility functions
**
** These functions manipulate struct utmp, taking system differences
** into account.
**/
#if defined(USE_UTMP) || defined (USE_WTMP) || defined (USE_LOGIN)
/* build the utmp structure */
void
set_utmp_time(struct logininfo *li, struct utmp *ut)
{
# if defined(HAVE_TV_IN_UTMP)
ut->ut_tv.tv_sec = li->tv_sec;
ut->ut_tv.tv_usec = li->tv_usec;
# elif defined(HAVE_TIME_IN_UTMP)
ut->ut_time = li->tv_sec;
# endif
}
void
construct_utmp(struct logininfo *li,
struct utmp *ut)
{
# ifdef HAVE_ADDR_V6_IN_UTMP
struct sockaddr_in6 *sa6;
# endif
memset(ut, '\0', sizeof(*ut));
/* First fill out fields used for both logins and logouts */
# ifdef HAVE_ID_IN_UTMP
line_abbrevname(ut->ut_id, li->line, sizeof(ut->ut_id));
# endif
# ifdef HAVE_TYPE_IN_UTMP
/* This is done here to keep utmp constants out of struct logininfo */
switch (li->type) {
case LTYPE_LOGIN:
ut->ut_type = USER_PROCESS;
break;
case LTYPE_LOGOUT:
ut->ut_type = DEAD_PROCESS;
break;
}
# endif
set_utmp_time(li, ut);
line_stripname(ut->ut_line, li->line, sizeof(ut->ut_line));
# ifdef HAVE_PID_IN_UTMP
ut->ut_pid = li->pid;
# endif
/* If we're logging out, leave all other fields blank */
if (li->type == LTYPE_LOGOUT)
return;
/*
* These fields are only used when logging in, and are blank
* for logouts.
*/
/* Use strncpy because we don't necessarily want null termination */
strncpy(ut->ut_name, li->username,
MIN_SIZEOF(ut->ut_name, li->username));
# ifdef HAVE_HOST_IN_UTMP
strncpy(ut->ut_host, li->hostname,
MIN_SIZEOF(ut->ut_host, li->hostname));
# endif
# ifdef HAVE_ADDR_IN_UTMP
/* this is just a 32-bit IP address */
if (li->hostaddr.sa.sa_family == AF_INET)
ut->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;
# endif
# ifdef HAVE_ADDR_V6_IN_UTMP
/* this is just a 128-bit IPv6 address */
if (li->hostaddr.sa.sa_family == AF_INET6) {
sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa);
memcpy(ut->ut_addr_v6, sa6->sin6_addr.s6_addr, 16);
if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
ut->ut_addr_v6[0] = ut->ut_addr_v6[3];
ut->ut_addr_v6[1] = 0;
ut->ut_addr_v6[2] = 0;
ut->ut_addr_v6[3] = 0;
}
}
# endif
}
#endif /* USE_UTMP || USE_WTMP || USE_LOGIN */
/**
** utmpx utility functions
**
** These functions manipulate struct utmpx, accounting for system
** variations.
**/
#if defined(USE_UTMPX) || defined (USE_WTMPX)
/* build the utmpx structure */
void
set_utmpx_time(struct logininfo *li, struct utmpx *utx)
{
# if defined(HAVE_TV_IN_UTMPX)
utx->ut_tv.tv_sec = li->tv_sec;
utx->ut_tv.tv_usec = li->tv_usec;
# elif defined(HAVE_TIME_IN_UTMPX)
utx->ut_time = li->tv_sec;
# endif
}
void
construct_utmpx(struct logininfo *li, struct utmpx *utx)
{
# ifdef HAVE_ADDR_V6_IN_UTMP
struct sockaddr_in6 *sa6;
# endif
memset(utx, '\0', sizeof(*utx));
# ifdef HAVE_ID_IN_UTMPX
line_abbrevname(utx->ut_id, li->line, sizeof(utx->ut_id));
# endif
/* this is done here to keep utmp constants out of loginrec.h */
switch (li->type) {
case LTYPE_LOGIN:
utx->ut_type = USER_PROCESS;
break;
case LTYPE_LOGOUT:
utx->ut_type = DEAD_PROCESS;
break;
}
line_stripname(utx->ut_line, li->line, sizeof(utx->ut_line));
set_utmpx_time(li, utx);
utx->ut_pid = li->pid;
/* strncpy(): Don't necessarily want null termination */
strncpy(utx->ut_user, li->username,
MIN_SIZEOF(utx->ut_user, li->username));
if (li->type == LTYPE_LOGOUT)
return;
/*
* These fields are only used when logging in, and are blank
* for logouts.
*/
# ifdef HAVE_HOST_IN_UTMPX
strncpy(utx->ut_host, li->hostname,
MIN_SIZEOF(utx->ut_host, li->hostname));
# endif
# ifdef HAVE_ADDR_IN_UTMPX
/* this is just a 32-bit IP address */
if (li->hostaddr.sa.sa_family == AF_INET)
utx->ut_addr = li->hostaddr.sa_in.sin_addr.s_addr;
# endif
# ifdef HAVE_ADDR_V6_IN_UTMP
/* this is just a 128-bit IPv6 address */
if (li->hostaddr.sa.sa_family == AF_INET6) {
sa6 = ((struct sockaddr_in6 *)&li->hostaddr.sa);
memcpy(utx->ut_addr_v6, sa6->sin6_addr.s6_addr, 16);
if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) {
utx->ut_addr_v6[0] = utx->ut_addr_v6[3];
utx->ut_addr_v6[1] = 0;
utx->ut_addr_v6[2] = 0;
utx->ut_addr_v6[3] = 0;
}
}
# endif
# ifdef HAVE_SYSLEN_IN_UTMPX
/* ut_syslen is the length of the utx_host string */
utx->ut_syslen = MIN(strlen(li->hostname), sizeof(utx->ut_host));
# endif
}
#endif /* USE_UTMPX || USE_WTMPX */
/**
** Low-level utmp functions
**/
/* FIXME: (ATL) utmp_write_direct needs testing */
#ifdef USE_UTMP
/* if we can, use pututline() etc. */
# if !defined(DISABLE_PUTUTLINE) && defined(HAVE_SETUTENT) && \
defined(HAVE_PUTUTLINE)
# define UTMP_USE_LIBRARY
# endif
/* write a utmp entry with the system's help (pututline() and pals) */
# ifdef UTMP_USE_LIBRARY
static int
utmp_write_library(struct logininfo *li, struct utmp *ut)
{
setutent();
pututline(ut);
# ifdef HAVE_ENDUTENT
endutent();
# endif
return (1);
}
# else /* UTMP_USE_LIBRARY */
/*
* Write a utmp entry direct to the file
* This is a slightly modification of code in OpenBSD's login.c
*/
static int
utmp_write_direct(struct logininfo *li, struct utmp *ut)
{
struct utmp old_ut;
register int fd;
int tty;
/* FIXME: (ATL) ttyslot() needs local implementation */
#if defined(HAVE_GETTTYENT)
struct ttyent *ty;
tty=0;
setttyent();
while (NULL != (ty = getttyent())) {
tty++;
if (!strncmp(ty->ty_name, ut->ut_line, sizeof(ut->ut_line)))
break;
}
endttyent();
if (NULL == ty) {
logit("%s: tty not found", __func__);
return (0);
}
#else /* FIXME */
tty = ttyslot(); /* seems only to work for /dev/ttyp? style names */
#endif /* HAVE_GETTTYENT */
if (tty > 0 && (fd = open(UTMP_FILE, O_RDWR|O_CREAT, 0644)) >= 0) {
off_t pos, ret;
pos = (off_t)tty * sizeof(struct utmp);
if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {
logit("%s: lseek: %s", __func__, strerror(errno));
close(fd);
return (0);
}
if (ret != pos) {
logit("%s: Couldn't seek to tty %d slot in %s",
__func__, tty, UTMP_FILE);
close(fd);
return (0);
}
/*
* Prevent luser from zero'ing out ut_host.
* If the new ut_line is empty but the old one is not
* and ut_line and ut_name match, preserve the old ut_line.
*/
if (atomicio(read, fd, &old_ut, sizeof(old_ut)) == sizeof(old_ut) &&
(ut->ut_host[0] == '\0') && (old_ut.ut_host[0] != '\0') &&
(strncmp(old_ut.ut_line, ut->ut_line, sizeof(ut->ut_line)) == 0) &&
(strncmp(old_ut.ut_name, ut->ut_name, sizeof(ut->ut_name)) == 0))
memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host));
if ((ret = lseek(fd, pos, SEEK_SET)) == -1) {
logit("%s: lseek: %s", __func__, strerror(errno));
close(fd);
return (0);
}
if (ret != pos) {
logit("%s: Couldn't seek to tty %d slot in %s",
__func__, tty, UTMP_FILE);
close(fd);
return (0);
}
if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
logit("%s: error writing %s: %s", __func__,
UTMP_FILE, strerror(errno));
close(fd);
return (0);
}
close(fd);
return (1);
} else {
return (0);
}
}
# endif /* UTMP_USE_LIBRARY */
static int
utmp_perform_login(struct logininfo *li)
{
struct utmp ut;
construct_utmp(li, &ut);
# ifdef UTMP_USE_LIBRARY
if (!utmp_write_library(li, &ut)) {
logit("%s: utmp_write_library() failed", __func__);
return (0);
}
# else
if (!utmp_write_direct(li, &ut)) {
logit("%s: utmp_write_direct() failed", __func__);
return (0);
}
# endif
return (1);
}
static int
utmp_perform_logout(struct logininfo *li)
{
struct utmp ut;
construct_utmp(li, &ut);
# ifdef UTMP_USE_LIBRARY
if (!utmp_write_library(li, &ut)) {
logit("%s: utmp_write_library() failed", __func__);
return (0);
}
# else
if (!utmp_write_direct(li, &ut)) {
logit("%s: utmp_write_direct() failed", __func__);
return (0);
}
# endif
return (1);
}
int
utmp_write_entry(struct logininfo *li)
{
switch(li->type) {
case LTYPE_LOGIN:
return (utmp_perform_login(li));
case LTYPE_LOGOUT:
return (utmp_perform_logout(li));
default:
logit("%s: invalid type field", __func__);
return (0);
}
}
#endif /* USE_UTMP */
/**
** Low-level utmpx functions
**/
/* not much point if we don't want utmpx entries */
#ifdef USE_UTMPX
/* if we have the wherewithall, use pututxline etc. */
# if !defined(DISABLE_PUTUTXLINE) && defined(HAVE_SETUTXENT) && \
defined(HAVE_PUTUTXLINE)
# define UTMPX_USE_LIBRARY
# endif
/* write a utmpx entry with the system's help (pututxline() and pals) */
# ifdef UTMPX_USE_LIBRARY
static int
utmpx_write_library(struct logininfo *li, struct utmpx *utx)
{
setutxent();
pututxline(utx);
# ifdef HAVE_ENDUTXENT
endutxent();
# endif
return (1);
}
# else /* UTMPX_USE_LIBRARY */
/* write a utmp entry direct to the file */
static int
utmpx_write_direct(struct logininfo *li, struct utmpx *utx)
{
logit("%s: not implemented!", __func__);
return (0);
}
# endif /* UTMPX_USE_LIBRARY */
static int
utmpx_perform_login(struct logininfo *li)
{
struct utmpx utx;
construct_utmpx(li, &utx);
# ifdef UTMPX_USE_LIBRARY
if (!utmpx_write_library(li, &utx)) {
logit("%s: utmp_write_library() failed", __func__);
return (0);
}
# else
if (!utmpx_write_direct(li, &ut)) {
logit("%s: utmp_write_direct() failed", __func__);
return (0);
}
# endif
return (1);
}
static int
utmpx_perform_logout(struct logininfo *li)
{
struct utmpx utx;
construct_utmpx(li, &utx);
# ifdef HAVE_ID_IN_UTMPX
line_abbrevname(utx.ut_id, li->line, sizeof(utx.ut_id));
# endif
# ifdef HAVE_TYPE_IN_UTMPX
utx.ut_type = DEAD_PROCESS;
# endif
# ifdef UTMPX_USE_LIBRARY
utmpx_write_library(li, &utx);
# else
utmpx_write_direct(li, &utx);
# endif
return (1);
}
int
utmpx_write_entry(struct logininfo *li)
{
switch(li->type) {
case LTYPE_LOGIN:
return (utmpx_perform_login(li));
case LTYPE_LOGOUT:
return (utmpx_perform_logout(li));
default:
logit("%s: invalid type field", __func__);
return (0);
}
}
#endif /* USE_UTMPX */
/**
** Low-level wtmp functions
**/
#ifdef USE_WTMP
/*
* Write a wtmp entry direct to the end of the file
* This is a slight modification of code in OpenBSD's logwtmp.c
*/
static int
wtmp_write(struct logininfo *li, struct utmp *ut)
{
struct stat buf;
int fd, ret = 1;
if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) < 0) {
logit("%s: problem writing %s: %s", __func__,
WTMP_FILE, strerror(errno));
return (0);
}
if (fstat(fd, &buf) == 0)
if (atomicio(vwrite, fd, ut, sizeof(*ut)) != sizeof(*ut)) {
ftruncate(fd, buf.st_size);
logit("%s: problem writing %s: %s", __func__,
WTMP_FILE, strerror(errno));
ret = 0;
}
close(fd);
return (ret);
}
static int
wtmp_perform_login(struct logininfo *li)
{
struct utmp ut;
construct_utmp(li, &ut);
return (wtmp_write(li, &ut));
}
static int
wtmp_perform_logout(struct logininfo *li)
{
struct utmp ut;
construct_utmp(li, &ut);
return (wtmp_write(li, &ut));
}
int
wtmp_write_entry(struct logininfo *li)
{
switch(li->type) {
case LTYPE_LOGIN:
return (wtmp_perform_login(li));
case LTYPE_LOGOUT:
return (wtmp_perform_logout(li));
default:
logit("%s: invalid type field", __func__);
return (0);
}
}
/*
* Notes on fetching login data from wtmp/wtmpx
*
* Logouts are usually recorded with (amongst other things) a blank
* username on a given tty line. However, some systems (HP-UX is one)
* leave all fields set, but change the ut_type field to DEAD_PROCESS.
*
* Since we're only looking for logins here, we know that the username
* must be set correctly. On systems that leave it in, we check for
* ut_type==USER_PROCESS (indicating a login.)
*
* Portability: Some systems may set something other than USER_PROCESS
* to indicate a login process. I don't know of any as I write. Also,
* it's possible that some systems may both leave the username in
* place and not have ut_type.
*/
/* return true if this wtmp entry indicates a login */
static int
wtmp_islogin(struct logininfo *li, struct utmp *ut)
{
if (strncmp(li->username, ut->ut_name,
MIN_SIZEOF(li->username, ut->ut_name)) == 0) {
# ifdef HAVE_TYPE_IN_UTMP
if (ut->ut_type & USER_PROCESS)
return (1);
# else
return (1);
# endif
}
return (0);
}
int
wtmp_get_entry(struct logininfo *li)
{
struct stat st;
struct utmp ut;
int fd, found = 0;
/* Clear the time entries in our logininfo */
li->tv_sec = li->tv_usec = 0;
if ((fd = open(WTMP_FILE, O_RDONLY)) < 0) {
logit("%s: problem opening %s: %s", __func__,
WTMP_FILE, strerror(errno));
return (0);
}
if (fstat(fd, &st) != 0) {
logit("%s: couldn't stat %s: %s", __func__,
WTMP_FILE, strerror(errno));
close(fd);
return (0);
}
/* Seek to the start of the last struct utmp */
if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_END) == -1) {
/* Looks like we've got a fresh wtmp file */
close(fd);
return (0);
}
while (!found) {
if (atomicio(read, fd, &ut, sizeof(ut)) != sizeof(ut)) {
logit("%s: read of %s failed: %s", __func__,
WTMP_FILE, strerror(errno));
close (fd);
return (0);
}
if (wtmp_islogin(li, &ut) ) {
found = 1;
/*
* We've already checked for a time in struct
* utmp, in login_getlast()
*/
# ifdef HAVE_TIME_IN_UTMP
li->tv_sec = ut.ut_time;
# else
# if HAVE_TV_IN_UTMP
li->tv_sec = ut.ut_tv.tv_sec;
# endif
# endif
line_fullname(li->line, ut.ut_line,
MIN_SIZEOF(li->line, ut.ut_line));
# ifdef HAVE_HOST_IN_UTMP
strlcpy(li->hostname, ut.ut_host,
MIN_SIZEOF(li->hostname, ut.ut_host));
# endif
continue;
}
/* Seek back 2 x struct utmp */
if (lseek(fd, -(off_t)(2 * sizeof(struct utmp)), SEEK_CUR) == -1) {
/* We've found the start of the file, so quit */
close(fd);
return (0);
}
}
/* We found an entry. Tidy up and return */
close(fd);
return (1);
}
# endif /* USE_WTMP */
/**
** Low-level wtmpx functions
**/
#ifdef USE_WTMPX
/*
* Write a wtmpx entry direct to the end of the file
* This is a slight modification of code in OpenBSD's logwtmp.c
*/
static int
wtmpx_write(struct logininfo *li, struct utmpx *utx)
{
#ifndef HAVE_UPDWTMPX
struct stat buf;
int fd, ret = 1;
if ((fd = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0)) < 0) {
logit("%s: problem opening %s: %s", __func__,
WTMPX_FILE, strerror(errno));
return (0);
}
if (fstat(fd, &buf) == 0)
if (atomicio(vwrite, fd, utx, sizeof(*utx)) != sizeof(*utx)) {
ftruncate(fd, buf.st_size);
logit("%s: problem writing %s: %s", __func__,
WTMPX_FILE, strerror(errno));
ret = 0;
}
close(fd);
return (ret);
#else
updwtmpx(WTMPX_FILE, utx);
return (1);
#endif
}
static int
wtmpx_perform_login(struct logininfo *li)
{
struct utmpx utx;
construct_utmpx(li, &utx);
return (wtmpx_write(li, &utx));
}
static int
wtmpx_perform_logout(struct logininfo *li)
{
struct utmpx utx;
construct_utmpx(li, &utx);
return (wtmpx_write(li, &utx));
}
int
wtmpx_write_entry(struct logininfo *li)
{
switch(li->type) {
case LTYPE_LOGIN:
return (wtmpx_perform_login(li));
case LTYPE_LOGOUT:
return (wtmpx_perform_logout(li));
default:
logit("%s: invalid type field", __func__);
return (0);
}
}
/* Please see the notes above wtmp_islogin() for information about the
next two functions */
/* Return true if this wtmpx entry indicates a login */
static int
wtmpx_islogin(struct logininfo *li, struct utmpx *utx)
{
if (strncmp(li->username, utx->ut_user,
MIN_SIZEOF(li->username, utx->ut_user)) == 0 ) {
# ifdef HAVE_TYPE_IN_UTMPX
if (utx->ut_type == USER_PROCESS)
return (1);
# else
return (1);
# endif
}
return (0);
}
int
wtmpx_get_entry(struct logininfo *li)
{
struct stat st;
struct utmpx utx;
int fd, found=0;
/* Clear the time entries */
li->tv_sec = li->tv_usec = 0;
if ((fd = open(WTMPX_FILE, O_RDONLY)) < 0) {
logit("%s: problem opening %s: %s", __func__,
WTMPX_FILE, strerror(errno));
return (0);
}
if (fstat(fd, &st) != 0) {
logit("%s: couldn't stat %s: %s", __func__,
WTMPX_FILE, strerror(errno));
close(fd);
return (0);
}
/* Seek to the start of the last struct utmpx */
if (lseek(fd, -(off_t)sizeof(struct utmpx), SEEK_END) == -1 ) {
/* probably a newly rotated wtmpx file */
close(fd);
return (0);
}
while (!found) {
if (atomicio(read, fd, &utx, sizeof(utx)) != sizeof(utx)) {
logit("%s: read of %s failed: %s", __func__,
WTMPX_FILE, strerror(errno));
close (fd);
return (0);
}
/*
* Logouts are recorded as a blank username on a particular
* line. So, we just need to find the username in struct utmpx
*/
if (wtmpx_islogin(li, &utx)) {
found = 1;
# if defined(HAVE_TV_IN_UTMPX)
li->tv_sec = utx.ut_tv.tv_sec;
# elif defined(HAVE_TIME_IN_UTMPX)
li->tv_sec = utx.ut_time;
# endif
line_fullname(li->line, utx.ut_line, sizeof(li->line));
# if defined(HAVE_HOST_IN_UTMPX)
strlcpy(li->hostname, utx.ut_host,
MIN_SIZEOF(li->hostname, utx.ut_host));
# endif
continue;
}
if (lseek(fd, -(off_t)(2 * sizeof(struct utmpx)), SEEK_CUR) == -1) {
close(fd);
return (0);
}
}
close(fd);
return (1);
}
#endif /* USE_WTMPX */
/**
** Low-level libutil login() functions
**/
#ifdef USE_LOGIN
static int
syslogin_perform_login(struct logininfo *li)
{
struct utmp *ut;
ut = xmalloc(sizeof(*ut));
construct_utmp(li, ut);
login(ut);
free(ut);
return (1);
}
static int
syslogin_perform_logout(struct logininfo *li)
{
# ifdef HAVE_LOGOUT
char line[UT_LINESIZE];
(void)line_stripname(line, li->line, sizeof(line));
if (!logout(line))
logit("%s: logout() returned an error", __func__);
# ifdef HAVE_LOGWTMP
else
logwtmp(line, "", "");
# endif
/* FIXME: (ATL - if the need arises) What to do if we have
* login, but no logout? what if logout but no logwtmp? All
* routines are in libutil so they should all be there,
* but... */
# endif
return (1);
}
int
syslogin_write_entry(struct logininfo *li)
{
switch (li->type) {
case LTYPE_LOGIN:
return (syslogin_perform_login(li));
case LTYPE_LOGOUT:
return (syslogin_perform_logout(li));
default:
logit("%s: Invalid type field", __func__);
return (0);
}
}
#endif /* USE_LOGIN */
/* end of file log-syslogin.c */
/**
** Low-level lastlog functions
**/
#ifdef USE_LASTLOG
#if !defined(LASTLOG_WRITE_PUTUTXLINE) || !defined(HAVE_GETLASTLOGXBYNAME)
/* open the file (using filemode) and seek to the login entry */
static int
lastlog_openseek(struct logininfo *li, int *fd, int filemode)
{
off_t offset;
char lastlog_file[1024];
struct stat st;
if (stat(LASTLOG_FILE, &st) != 0) {
logit("%s: Couldn't stat %s: %s", __func__,
LASTLOG_FILE, strerror(errno));
return (0);
}
if (S_ISDIR(st.st_mode)) {
snprintf(lastlog_file, sizeof(lastlog_file), "%s/%s",
LASTLOG_FILE, li->username);
} else if (S_ISREG(st.st_mode)) {
strlcpy(lastlog_file, LASTLOG_FILE, sizeof(lastlog_file));
} else {
logit("%s: %.100s is not a file or directory!", __func__,
LASTLOG_FILE);
return (0);
}
*fd = open(lastlog_file, filemode, 0600);
if (*fd < 0) {
debug("%s: Couldn't open %s: %s", __func__,
lastlog_file, strerror(errno));
return (0);
}
if (S_ISREG(st.st_mode)) {
/* find this uid's offset in the lastlog file */
offset = (off_t) ((u_long)li->uid * sizeof(struct lastlog));
if (lseek(*fd, offset, SEEK_SET) != offset) {
logit("%s: %s->lseek(): %s", __func__,
lastlog_file, strerror(errno));
close(*fd);
return (0);
}
}
return (1);
}
#endif /* !LASTLOG_WRITE_PUTUTXLINE || !HAVE_GETLASTLOGXBYNAME */
#ifdef LASTLOG_WRITE_PUTUTXLINE
int
lastlog_write_entry(struct logininfo *li)
{
switch(li->type) {
case LTYPE_LOGIN:
return 1; /* lastlog written by pututxline */
default:
logit("lastlog_write_entry: Invalid type field");
return 0;
}
}
#else /* LASTLOG_WRITE_PUTUTXLINE */
int
lastlog_write_entry(struct logininfo *li)
{
struct lastlog last;
int fd;
switch(li->type) {
case LTYPE_LOGIN:
/* create our struct lastlog */
memset(&last, '\0', sizeof(last));
line_stripname(last.ll_line, li->line, sizeof(last.ll_line));
strlcpy(last.ll_host, li->hostname,
MIN_SIZEOF(last.ll_host, li->hostname));
last.ll_time = li->tv_sec;
if (!lastlog_openseek(li, &fd, O_RDWR|O_CREAT))
return (0);
/* write the entry */
if (atomicio(vwrite, fd, &last, sizeof(last)) != sizeof(last)) {
close(fd);
logit("%s: Error writing to %s: %s", __func__,
LASTLOG_FILE, strerror(errno));
return (0);
}
close(fd);
return (1);
default:
logit("%s: Invalid type field", __func__);
return (0);
}
}
#endif /* LASTLOG_WRITE_PUTUTXLINE */
#ifdef HAVE_GETLASTLOGXBYNAME
int
lastlog_get_entry(struct logininfo *li)
{
struct lastlogx l, *ll;
if ((ll = getlastlogxbyname(li->username, &l)) == NULL) {
memset(&l, '\0', sizeof(l));
ll = &l;
}
line_fullname(li->line, ll->ll_line, sizeof(li->line));
strlcpy(li->hostname, ll->ll_host,
MIN_SIZEOF(li->hostname, ll->ll_host));
li->tv_sec = ll->ll_tv.tv_sec;
li->tv_usec = ll->ll_tv.tv_usec;
return (1);
}
#else /* HAVE_GETLASTLOGXBYNAME */
int
lastlog_get_entry(struct logininfo *li)
{
struct lastlog last;
int fd, ret;
if (!lastlog_openseek(li, &fd, O_RDONLY))
return (0);
ret = atomicio(read, fd, &last, sizeof(last));
close(fd);
switch (ret) {
case 0:
memset(&last, '\0', sizeof(last));
/* FALLTHRU */
case sizeof(last):
line_fullname(li->line, last.ll_line, sizeof(li->line));
strlcpy(li->hostname, last.ll_host,
MIN_SIZEOF(li->hostname, last.ll_host));
li->tv_sec = last.ll_time;
return (1);
case -1:
error("%s: Error reading from %s: %s", __func__,
LASTLOG_FILE, strerror(errno));
return (0);
default:
error("%s: Error reading from %s: Expecting %d, got %d",
__func__, LASTLOG_FILE, (int)sizeof(last), ret);
return (0);
}
/* NOTREACHED */
return (0);
}
#endif /* HAVE_GETLASTLOGXBYNAME */
#endif /* USE_LASTLOG */
#if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \
defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER)
int
utmpx_get_entry(struct logininfo *li)
{
struct utmpx *utx;
if (setutxdb(UTXDB_LASTLOGIN, NULL) != 0)
return (0);
utx = getutxuser(li->username);
if (utx == NULL) {
endutxent();
return (0);
}
line_fullname(li->line, utx->ut_line,
MIN_SIZEOF(li->line, utx->ut_line));
strlcpy(li->hostname, utx->ut_host,
MIN_SIZEOF(li->hostname, utx->ut_host));
li->tv_sec = utx->ut_tv.tv_sec;
li->tv_usec = utx->ut_tv.tv_usec;
endutxent();
return (1);
}
#endif /* USE_UTMPX && HAVE_SETUTXDB && UTXDB_LASTLOGIN && HAVE_GETUTXUSER */
#ifdef USE_BTMP
/*
* Logs failed login attempts in _PATH_BTMP if that exists.
* The most common login failure is to give password instead of username.
* So the _PATH_BTMP file checked for the correct permission, so that
* only root can read it.
*/
void
-record_failed_login(const char *username, const char *hostname,
+record_failed_login(struct ssh *ssh, const char *username, const char *hostname,
const char *ttyn)
{
int fd;
struct utmp ut;
struct sockaddr_storage from;
socklen_t fromlen = sizeof(from);
struct sockaddr_in *a4;
struct sockaddr_in6 *a6;
time_t t;
struct stat fst;
if (geteuid() != 0)
return;
if ((fd = open(_PATH_BTMP, O_WRONLY | O_APPEND)) < 0) {
debug("Unable to open the btmp file %s: %s", _PATH_BTMP,
strerror(errno));
return;
}
if (fstat(fd, &fst) < 0) {
logit("%s: fstat of %s failed: %s", __func__, _PATH_BTMP,
strerror(errno));
goto out;
}
if((fst.st_mode & (S_IXGRP | S_IRWXO)) || (fst.st_uid != 0)){
logit("Excess permission or bad ownership on file %s",
_PATH_BTMP);
goto out;
}
memset(&ut, 0, sizeof(ut));
/* strncpy because we don't necessarily want nul termination */
strncpy(ut.ut_user, username, sizeof(ut.ut_user));
strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line));
time(&t);
ut.ut_time = t; /* ut_time is not always a time_t */
ut.ut_type = LOGIN_PROCESS;
ut.ut_pid = getpid();
/* strncpy because we don't necessarily want nul termination */
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
- if (packet_connection_is_on_socket() &&
- getpeername(packet_get_connection_in(),
+ if (ssh_packet_connection_is_on_socket(ssh) &&
+ getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) == 0) {
ipv64_normalise_mapped(&from, &fromlen);
if (from.ss_family == AF_INET) {
a4 = (struct sockaddr_in *)&from;
memcpy(&ut.ut_addr, &(a4->sin_addr),
MIN_SIZEOF(ut.ut_addr, a4->sin_addr));
}
#ifdef HAVE_ADDR_V6_IN_UTMP
if (from.ss_family == AF_INET6) {
a6 = (struct sockaddr_in6 *)&from;
memcpy(&ut.ut_addr_v6, &(a6->sin6_addr),
MIN_SIZEOF(ut.ut_addr_v6, a6->sin6_addr));
}
#endif
}
if (atomicio(vwrite, fd, &ut, sizeof(ut)) != sizeof(ut))
error("Failed to write to %s: %s", _PATH_BTMP,
strerror(errno));
out:
close(fd);
}
#endif /* USE_BTMP */
diff --git a/loginrec.h b/loginrec.h
index 28923e7812e5..62cc0e78c945 100644
--- a/loginrec.h
+++ b/loginrec.h
@@ -1,131 +1,134 @@
#ifndef _HAVE_LOGINREC_H_
#define _HAVE_LOGINREC_H_
/*
* Copyright (c) 2000 Andre Lucas. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
** loginrec.h: platform-independent login recording and lastlog retrieval
**/
#include "includes.h"
+struct ssh;
+
/**
** you should use the login_* calls to work around platform dependencies
**/
/*
* login_netinfo structure
*/
union login_netinfo {
struct sockaddr sa;
struct sockaddr_in sa_in;
struct sockaddr_storage sa_storage;
};
/*
* * logininfo structure *
*/
/* types - different to utmp.h 'type' macros */
/* (though set to the same value as linux, openbsd and others...) */
#define LTYPE_LOGIN 7
#define LTYPE_LOGOUT 8
/* string lengths - set very long */
#define LINFO_PROGSIZE 64
#define LINFO_LINESIZE 64
#define LINFO_NAMESIZE 512
#define LINFO_HOSTSIZE 256
struct logininfo {
char progname[LINFO_PROGSIZE]; /* name of program (for PAM) */
int progname_null;
short int type; /* type of login (LTYPE_*) */
pid_t pid; /* PID of login process */
uid_t uid; /* UID of this user */
char line[LINFO_LINESIZE]; /* tty/pty name */
char username[LINFO_NAMESIZE]; /* login username */
char hostname[LINFO_HOSTSIZE]; /* remote hostname */
/* 'exit_status' structure components */
int exit; /* process exit status */
int termination; /* process termination status */
/* struct timeval (sys/time.h) isn't always available, if it isn't we'll
* use time_t's value as tv_sec and set tv_usec to 0
*/
unsigned int tv_sec;
unsigned int tv_usec;
union login_netinfo hostaddr; /* caller's host address(es) */
}; /* struct logininfo */
/*
* login recording functions
*/
/** 'public' functions */
/* construct a new login entry */
struct logininfo *login_alloc_entry(pid_t pid, const char *username,
const char *hostname, const char *line);
/* free a structure */
void login_free_entry(struct logininfo *li);
/* fill out a pre-allocated structure with useful information */
int login_init_entry(struct logininfo *li, pid_t pid, const char *username,
const char *hostname, const char *line);
/* place the current time in a logininfo struct */
void login_set_current_time(struct logininfo *li);
/* record the entry */
int login_login (struct logininfo *li);
int login_logout(struct logininfo *li);
#ifdef LOGIN_NEEDS_UTMPX
int login_utmp_only(struct logininfo *li);
#endif
/** End of public functions */
/* record the entry */
int login_write (struct logininfo *li);
int login_log_entry(struct logininfo *li);
/* set the network address based on network address type */
void login_set_addr(struct logininfo *li, const struct sockaddr *sa,
const unsigned int sa_size);
/*
* lastlog retrieval functions
*/
/* lastlog *entry* functions fill out a logininfo */
struct logininfo *login_get_lastlog(struct logininfo *li, const uid_t uid);
/* lastlog *time* functions return time_t equivalent (uint) */
unsigned int login_get_lastlog_time(const uid_t uid);
/* produce various forms of the line filename */
char *line_fullname(char *dst, const char *src, u_int dstsize);
char *line_stripname(char *dst, const char *src, int dstsize);
char *line_abbrevname(char *dst, const char *src, int dstsize);
-void record_failed_login(const char *, const char *, const char *);
+void record_failed_login(struct ssh *, const char *, const char *,
+ const char *);
#endif /* _HAVE_LOGINREC_H_ */
diff --git a/match.c b/match.c
index bb3e95f678ca..fcf69596d56e 100644
--- a/match.c
+++ b/match.c
@@ -1,350 +1,363 @@
-/* $OpenBSD: match.c,v 1.38 2018/07/04 13:49:31 djm Exp $ */
+/* $OpenBSD: match.c,v 1.39 2019/03/06 22:14:23 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Simple pattern matching, with '*' and '?' as wildcards.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "xmalloc.h"
#include "match.h"
#include "misc.h"
/*
* Returns true if the given string matches the pattern (which may contain ?
* and * as wildcards), and zero if it does not match.
*/
int
match_pattern(const char *s, const char *pattern)
{
for (;;) {
/* If at end of pattern, accept if also at end of string. */
if (!*pattern)
return !*s;
if (*pattern == '*') {
/* Skip the asterisk. */
pattern++;
/* If at end of pattern, accept immediately. */
if (!*pattern)
return 1;
/* If next character in pattern is known, optimize. */
if (*pattern != '?' && *pattern != '*') {
/*
* Look instances of the next character in
* pattern, and try to match starting from
* those.
*/
for (; *s; s++)
if (*s == *pattern &&
match_pattern(s + 1, pattern + 1))
return 1;
/* Failed. */
return 0;
}
/*
* Move ahead one character at a time and try to
* match at each position.
*/
for (; *s; s++)
if (match_pattern(s, pattern))
return 1;
/* Failed. */
return 0;
}
/*
* There must be at least one more character in the string.
* If we are at the end, fail.
*/
if (!*s)
return 0;
/* Check if the next character of the string is acceptable. */
if (*pattern != '?' && *pattern != *s)
return 0;
/* Move to the next character, both in string and in pattern. */
s++;
pattern++;
}
/* NOTREACHED */
}
/*
* Tries to match the string against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
* indicate negation). Returns -1 if negation matches, 1 if there is
* a positive match, 0 if there is no match at all.
*/
int
match_pattern_list(const char *string, const char *pattern, int dolower)
{
char sub[1024];
int negated;
int got_positive;
u_int i, subi, len = strlen(pattern);
got_positive = 0;
for (i = 0; i < len;) {
/* Check if the subpattern is negated. */
if (pattern[i] == '!') {
negated = 1;
i++;
} else
negated = 0;
/*
* Extract the subpattern up to a comma or end. Convert the
* subpattern to lowercase.
*/
for (subi = 0;
i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
subi++, i++)
sub[subi] = dolower && isupper((u_char)pattern[i]) ?
tolower((u_char)pattern[i]) : pattern[i];
/* If subpattern too long, return failure (no match). */
if (subi >= sizeof(sub) - 1)
return 0;
/* If the subpattern was terminated by a comma, then skip it. */
if (i < len && pattern[i] == ',')
i++;
/* Null-terminate the subpattern. */
sub[subi] = '\0';
/* Try to match the subpattern against the string. */
if (match_pattern(string, sub)) {
if (negated)
return -1; /* Negative */
else
got_positive = 1; /* Positive */
}
}
/*
* Return success if got a positive match. If there was a negative
* match, we have already returned -1 and never get here.
*/
return got_positive;
}
+/* Match a list representing users or groups. */
+int
+match_usergroup_pattern_list(const char *string, const char *pattern)
+{
+#ifdef HAVE_CYGWIN
+ /* Windows usernames may be Unicode and are not case sensitive */
+ return cygwin_ug_match_pattern_list(string, pattern);
+#else
+ /* Case insensitive match */
+ return match_pattern_list(string, pattern, 0);
+#endif
+}
+
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
* indicate negation). Returns -1 if negation matches, 1 if there is
* a positive match, 0 if there is no match at all.
*/
int
match_hostname(const char *host, const char *pattern)
{
char *hostcopy = xstrdup(host);
int r;
lowercase(hostcopy);
r = match_pattern_list(hostcopy, pattern, 1);
free(hostcopy);
return r;
}
/*
* returns 0 if we get a negative match for the hostname or the ip
* or if we get no match at all. returns -1 on error, or 1 on
* successful match.
*/
int
match_host_and_ip(const char *host, const char *ipaddr,
const char *patterns)
{
int mhost, mip;
if ((mip = addr_match_list(ipaddr, patterns)) == -2)
return -1; /* error in ipaddr match */
else if (host == NULL || ipaddr == NULL || mip == -1)
return 0; /* negative ip address match, or testing pattern */
/* negative hostname match */
if ((mhost = match_hostname(host, patterns)) == -1)
return 0;
/* no match at all */
if (mhost == 0 && mip == 0)
return 0;
return 1;
}
/*
* Match user, user@host_or_ip, user@host_or_ip_list against pattern.
* If user, host and ipaddr are all NULL then validate pattern/
* Returns -1 on invalid pattern, 0 on no match, 1 on match.
*/
int
match_user(const char *user, const char *host, const char *ipaddr,
const char *pattern)
{
char *p, *pat;
int ret;
/* test mode */
if (user == NULL && host == NULL && ipaddr == NULL) {
if ((p = strchr(pattern, '@')) != NULL &&
match_host_and_ip(NULL, NULL, p + 1) < 0)
return -1;
return 0;
}
if ((p = strchr(pattern,'@')) == NULL)
return match_pattern(user, pattern);
pat = xstrdup(pattern);
p = strchr(pat, '@');
*p++ = '\0';
if ((ret = match_pattern(user, pat)) == 1)
ret = match_host_and_ip(host, ipaddr, p);
free(pat);
return ret;
}
/*
* Returns first item from client-list that is also supported by server-list,
* caller must free the returned string.
*/
#define MAX_PROP 40
#define SEP ","
char *
match_list(const char *client, const char *server, u_int *next)
{
char *sproposals[MAX_PROP];
char *c, *s, *p, *ret, *cp, *sp;
int i, j, nproposals;
c = cp = xstrdup(client);
s = sp = xstrdup(server);
for ((p = strsep(&sp, SEP)), i=0; p && *p != '\0';
(p = strsep(&sp, SEP)), i++) {
if (i < MAX_PROP)
sproposals[i] = p;
else
break;
}
nproposals = i;
for ((p = strsep(&cp, SEP)), i=0; p && *p != '\0';
(p = strsep(&cp, SEP)), i++) {
for (j = 0; j < nproposals; j++) {
if (strcmp(p, sproposals[j]) == 0) {
ret = xstrdup(p);
if (next != NULL)
*next = (cp == NULL) ?
strlen(c) : (u_int)(cp - c);
free(c);
free(s);
return ret;
}
}
}
if (next != NULL)
*next = strlen(c);
free(c);
free(s);
return NULL;
}
/*
* Filter proposal using pattern-list filter.
* "blacklist" determines sense of filter:
* non-zero indicates that items matching filter should be excluded.
* zero indicates that only items matching filter should be included.
* returns NULL on allocation error, otherwise caller must free result.
*/
static char *
filter_list(const char *proposal, const char *filter, int blacklist)
{
size_t len = strlen(proposal) + 1;
char *fix_prop = malloc(len);
char *orig_prop = strdup(proposal);
char *cp, *tmp;
int r;
if (fix_prop == NULL || orig_prop == NULL) {
free(orig_prop);
free(fix_prop);
return NULL;
}
tmp = orig_prop;
*fix_prop = '\0';
while ((cp = strsep(&tmp, ",")) != NULL) {
r = match_pattern_list(cp, filter, 0);
if ((blacklist && r != 1) || (!blacklist && r == 1)) {
if (*fix_prop != '\0')
strlcat(fix_prop, ",", len);
strlcat(fix_prop, cp, len);
}
}
free(orig_prop);
return fix_prop;
}
/*
* Filters a comma-separated list of strings, excluding any entry matching
* the 'filter' pattern list. Caller must free returned string.
*/
char *
match_filter_blacklist(const char *proposal, const char *filter)
{
return filter_list(proposal, filter, 1);
}
/*
* Filters a comma-separated list of strings, including only entries matching
* the 'filter' pattern list. Caller must free returned string.
*/
char *
match_filter_whitelist(const char *proposal, const char *filter)
{
return filter_list(proposal, filter, 0);
}
diff --git a/match.h b/match.h
index 852b1a5cb164..3a8a6ecdc1da 100644
--- a/match.h
+++ b/match.h
@@ -1,29 +1,30 @@
-/* $OpenBSD: match.h,v 1.18 2018/07/04 13:49:31 djm Exp $ */
+/* $OpenBSD: match.h,v 1.19 2019/03/06 22:14:23 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef MATCH_H
#define MATCH_H
int match_pattern(const char *, const char *);
int match_pattern_list(const char *, const char *, int);
+int match_usergroup_pattern_list(const char *, const char *);
int match_hostname(const char *, const char *);
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
char *match_filter_blacklist(const char *, const char *);
char *match_filter_whitelist(const char *, const char *);
/* addrmatch.c */
int addr_match_list(const char *, const char *);
int addr_match_cidr_list(const char *, const char *);
#endif
diff --git a/misc.c b/misc.c
index bdc06fdb3332..009e02bc55c1 100644
--- a/misc.c
+++ b/misc.c
@@ -1,2039 +1,2120 @@
-/* $OpenBSD: misc.c,v 1.133 2018/10/05 14:26:09 naddy Exp $ */
+/* $OpenBSD: misc.c,v 1.137 2019/01/23 21:50:56 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <limits.h>
#ifdef HAVE_LIBGEN_H
# include <libgen.h>
#endif
+#include <poll.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#include <pwd.h>
#endif
#ifdef SSH_TUN_OPENBSD
#include <net/if.h>
#endif
#include "xmalloc.h"
#include "misc.h"
#include "log.h"
#include "ssh.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "platform.h"
/* remove newline at end of string */
char *
chop(char *s)
{
char *t = s;
while (*t) {
if (*t == '\n' || *t == '\r') {
*t = '\0';
return s;
}
t++;
}
return s;
}
/* set/unset filedescriptor to non-blocking */
int
set_nonblock(int fd)
{
int val;
val = fcntl(fd, F_GETFL);
if (val < 0) {
error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));
return (-1);
}
if (val & O_NONBLOCK) {
debug3("fd %d is O_NONBLOCK", fd);
return (0);
}
debug2("fd %d setting O_NONBLOCK", fd);
val |= O_NONBLOCK;
if (fcntl(fd, F_SETFL, val) == -1) {
debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
strerror(errno));
return (-1);
}
return (0);
}
int
unset_nonblock(int fd)
{
int val;
val = fcntl(fd, F_GETFL);
if (val < 0) {
error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));
return (-1);
}
if (!(val & O_NONBLOCK)) {
debug3("fd %d is not O_NONBLOCK", fd);
return (0);
}
debug("fd %d clearing O_NONBLOCK", fd);
val &= ~O_NONBLOCK;
if (fcntl(fd, F_SETFL, val) == -1) {
debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
fd, strerror(errno));
return (-1);
}
return (0);
}
const char *
ssh_gai_strerror(int gaierr)
{
if (gaierr == EAI_SYSTEM && errno != 0)
return strerror(errno);
return gai_strerror(gaierr);
}
/* disable nagle on socket */
void
set_nodelay(int fd)
{
int opt;
socklen_t optlen;
optlen = sizeof opt;
if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
return;
}
if (opt == 1) {
debug2("fd %d is TCP_NODELAY", fd);
return;
}
opt = 1;
debug2("fd %d setting TCP_NODELAY", fd);
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
}
/* Allow local port reuse in TIME_WAIT */
int
set_reuseaddr(int fd)
{
int on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
return -1;
}
return 0;
}
/* Get/set routing domain */
char *
get_rdomain(int fd)
{
#if defined(HAVE_SYS_GET_RDOMAIN)
return sys_get_rdomain(fd);
#elif defined(__OpenBSD__)
int rtable;
char *ret;
socklen_t len = sizeof(rtable);
if (getsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, &len) == -1) {
error("Failed to get routing domain for fd %d: %s",
fd, strerror(errno));
return NULL;
}
xasprintf(&ret, "%d", rtable);
return ret;
#else /* defined(__OpenBSD__) */
return NULL;
#endif
}
int
set_rdomain(int fd, const char *name)
{
#if defined(HAVE_SYS_SET_RDOMAIN)
return sys_set_rdomain(fd, name);
#elif defined(__OpenBSD__)
int rtable;
const char *errstr;
if (name == NULL)
return 0; /* default table */
rtable = (int)strtonum(name, 0, 255, &errstr);
if (errstr != NULL) {
/* Shouldn't happen */
error("Invalid routing domain \"%s\": %s", name, errstr);
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_RTABLE,
&rtable, sizeof(rtable)) == -1) {
error("Failed to set routing domain %d on fd %d: %s",
rtable, fd, strerror(errno));
return -1;
}
return 0;
#else /* defined(__OpenBSD__) */
error("Setting routing domain is not supported on this platform");
return -1;
#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. */
#define WHITESPACE " \t\r\n"
#define QUOTE "\""
/* return next token in configuration line */
static char *
strdelim_internal(char **s, int split_equals)
{
char *old;
int wspace = 0;
if (*s == NULL)
return NULL;
old = *s;
*s = strpbrk(*s,
split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE);
if (*s == NULL)
return (old);
if (*s[0] == '\"') {
memmove(*s, *s + 1, strlen(*s)); /* move nul too */
/* Find matching quote */
if ((*s = strpbrk(*s, QUOTE)) == NULL) {
return (NULL); /* no matching quote */
} else {
*s[0] = '\0';
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
}
/* Allow only one '=' to be skipped */
if (split_equals && *s[0] == '=')
wspace = 1;
*s[0] = '\0';
/* Skip any extra whitespace after first token */
*s += strspn(*s + 1, WHITESPACE) + 1;
if (split_equals && *s[0] == '=' && !wspace)
*s += strspn(*s + 1, WHITESPACE) + 1;
return (old);
}
/*
* Return next token in configuration line; splts on whitespace or a
* single '=' character.
*/
char *
strdelim(char **s)
{
return strdelim_internal(s, 1);
}
/*
* Return next token in configuration line; splts on whitespace only.
*/
char *
strdelimw(char **s)
{
return strdelim_internal(s, 0);
}
struct passwd *
pwcopy(struct passwd *pw)
{
struct passwd *copy = xcalloc(1, sizeof(*copy));
copy->pw_name = xstrdup(pw->pw_name);
copy->pw_passwd = xstrdup(pw->pw_passwd);
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
copy->pw_gecos = xstrdup(pw->pw_gecos);
#endif
copy->pw_uid = pw->pw_uid;
copy->pw_gid = pw->pw_gid;
#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
copy->pw_expire = pw->pw_expire;
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
copy->pw_change = pw->pw_change;
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
copy->pw_class = xstrdup(pw->pw_class);
#endif
copy->pw_dir = xstrdup(pw->pw_dir);
copy->pw_shell = xstrdup(pw->pw_shell);
return copy;
}
/*
* Convert ASCII string to TCP/IP port number.
* Port must be >=0 and <=65535.
* Return -1 if invalid.
*/
int
a2port(const char *s)
{
struct servent *se;
long long port;
const char *errstr;
port = strtonum(s, 0, 65535, &errstr);
if (errstr == NULL)
return (int)port;
if ((se = getservbyname(s, "tcp")) != NULL)
return ntohs(se->s_port);
return -1;
}
int
a2tun(const char *s, int *remote)
{
const char *errstr = NULL;
char *sp, *ep;
int tun;
if (remote != NULL) {
*remote = SSH_TUNID_ANY;
sp = xstrdup(s);
if ((ep = strchr(sp, ':')) == NULL) {
free(sp);
return (a2tun(s, NULL));
}
ep[0] = '\0'; ep++;
*remote = a2tun(ep, NULL);
tun = a2tun(sp, NULL);
free(sp);
return (*remote == SSH_TUNID_ERR ? *remote : tun);
}
if (strcasecmp(s, "any") == 0)
return (SSH_TUNID_ANY);
tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
if (errstr != NULL)
return (SSH_TUNID_ERR);
return (tun);
}
#define SECONDS 1
#define MINUTES (SECONDS * 60)
#define HOURS (MINUTES * 60)
#define DAYS (HOURS * 24)
#define WEEKS (DAYS * 7)
/*
* Convert a time string into seconds; format is
* a sequence of:
* time[qualifier]
*
* Valid time qualifiers are:
* <none> seconds
* s|S seconds
* m|M minutes
* h|H hours
* d|D days
* w|W weeks
*
* Examples:
* 90m 90 minutes
* 1h30m 90 minutes
* 2d 2 days
* 1w 1 week
*
* Return -1 if time string is invalid.
*/
long
convtime(const char *s)
{
long total, secs, multiplier = 1;
const char *p;
char *endp;
errno = 0;
total = 0;
p = s;
if (p == NULL || *p == '\0')
return -1;
while (*p) {
secs = strtol(p, &endp, 10);
if (p == endp ||
(errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
secs < 0)
return -1;
switch (*endp++) {
case '\0':
endp--;
break;
case 's':
case 'S':
break;
case 'm':
case 'M':
multiplier = MINUTES;
break;
case 'h':
case 'H':
multiplier = HOURS;
break;
case 'd':
case 'D':
multiplier = DAYS;
break;
case 'w':
case 'W':
multiplier = WEEKS;
break;
default:
return -1;
}
if (secs >= LONG_MAX / multiplier)
return -1;
secs *= multiplier;
if (total >= LONG_MAX - secs)
return -1;
total += secs;
if (total < 0)
return -1;
p = endp;
}
return total;
}
/*
* Returns a standardized host+port identifier string.
* Caller must free returned string.
*/
char *
put_host_port(const char *host, u_short port)
{
char *hoststr;
if (port == 0 || port == SSH_DEFAULT_PORT)
return(xstrdup(host));
if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
fatal("put_host_port: asprintf: %s", strerror(errno));
debug3("put_host_port: %s", hoststr);
return hoststr;
}
/*
* Search for next delimiter between hostnames/addresses and ports.
* Argument may be modified (for termination).
* Returns *cp if parsing succeeds.
* *cp is set to the start of the next field, if one was found.
* The delimiter char, if present, is stored in delim.
* If this is the last field, *cp is set to NULL.
*/
-static char *
+char *
hpdelim2(char **cp, char *delim)
{
char *s, *old;
if (cp == NULL || *cp == NULL)
return NULL;
old = s = *cp;
if (*s == '[') {
if ((s = strchr(s, ']')) == NULL)
return NULL;
else
s++;
} else if ((s = strpbrk(s, ":/")) == NULL)
s = *cp + strlen(*cp); /* skip to end (see first case below) */
switch (*s) {
case '\0':
*cp = NULL; /* no more fields*/
break;
case ':':
case '/':
if (delim != NULL)
*delim = *s;
*s = '\0'; /* terminate */
*cp = s + 1;
break;
default:
return NULL;
}
return old;
}
char *
hpdelim(char **cp)
{
return hpdelim2(cp, NULL);
}
char *
cleanhostname(char *host)
{
if (*host == '[' && host[strlen(host) - 1] == ']') {
host[strlen(host) - 1] = '\0';
return (host + 1);
} else
return host;
}
char *
colon(char *cp)
{
int flag = 0;
if (*cp == ':') /* Leading colon is part of file name. */
return NULL;
if (*cp == '[')
flag = 1;
for (; *cp; ++cp) {
if (*cp == '@' && *(cp+1) == '[')
flag = 1;
if (*cp == ']' && *(cp+1) == ':' && flag)
return (cp+1);
if (*cp == ':' && !flag)
return (cp);
if (*cp == '/')
return NULL;
}
return NULL;
}
/*
* Parse a [user@]host:[path] string.
* Caller must free returned user, host and path.
* Any of the pointer return arguments may be NULL (useful for syntax checking).
* If user was not specified then *userp will be set to NULL.
* If host was not specified then *hostp will be set to NULL.
* If path was not specified then *pathp will be set to ".".
* Returns 0 on success, -1 on failure.
*/
int
parse_user_host_path(const char *s, char **userp, char **hostp, char **pathp)
{
char *user = NULL, *host = NULL, *path = NULL;
char *sdup, *tmp;
int ret = -1;
if (userp != NULL)
*userp = NULL;
if (hostp != NULL)
*hostp = NULL;
if (pathp != NULL)
*pathp = NULL;
sdup = xstrdup(s);
/* Check for remote syntax: [user@]host:[path] */
if ((tmp = colon(sdup)) == NULL)
goto out;
/* Extract optional path */
*tmp++ = '\0';
if (*tmp == '\0')
tmp = ".";
path = xstrdup(tmp);
/* Extract optional user and mandatory host */
tmp = strrchr(sdup, '@');
if (tmp != NULL) {
*tmp++ = '\0';
host = xstrdup(cleanhostname(tmp));
if (*sdup != '\0')
user = xstrdup(sdup);
} else {
host = xstrdup(cleanhostname(sdup));
user = NULL;
}
/* Success */
if (userp != NULL) {
*userp = user;
user = NULL;
}
if (hostp != NULL) {
*hostp = host;
host = NULL;
}
if (pathp != NULL) {
*pathp = path;
path = NULL;
}
ret = 0;
out:
free(sdup);
free(user);
free(host);
free(path);
return ret;
}
/*
* Parse a [user@]host[:port] string.
* Caller must free returned user and host.
* Any of the pointer return arguments may be NULL (useful for syntax checking).
* If user was not specified then *userp will be set to NULL.
* If port was not specified then *portp will be -1.
* Returns 0 on success, -1 on failure.
*/
int
parse_user_host_port(const char *s, char **userp, char **hostp, int *portp)
{
char *sdup, *cp, *tmp;
char *user = NULL, *host = NULL;
int port = -1, ret = -1;
if (userp != NULL)
*userp = NULL;
if (hostp != NULL)
*hostp = NULL;
if (portp != NULL)
*portp = -1;
if ((sdup = tmp = strdup(s)) == NULL)
return -1;
/* Extract optional username */
if ((cp = strrchr(tmp, '@')) != NULL) {
*cp = '\0';
if (*tmp == '\0')
goto out;
if ((user = strdup(tmp)) == NULL)
goto out;
tmp = cp + 1;
}
/* Extract mandatory hostname */
if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0')
goto out;
host = xstrdup(cleanhostname(cp));
/* Convert and verify optional port */
if (tmp != NULL && *tmp != '\0') {
if ((port = a2port(tmp)) <= 0)
goto out;
}
/* Success */
if (userp != NULL) {
*userp = user;
user = NULL;
}
if (hostp != NULL) {
*hostp = host;
host = NULL;
}
if (portp != NULL)
*portp = port;
ret = 0;
out:
free(sdup);
free(user);
free(host);
return ret;
}
/*
* Converts a two-byte hex string to decimal.
* Returns the decimal value or -1 for invalid input.
*/
static int
hexchar(const char *s)
{
unsigned char result[2];
int i;
for (i = 0; i < 2; i++) {
if (s[i] >= '0' && s[i] <= '9')
result[i] = (unsigned char)(s[i] - '0');
else if (s[i] >= 'a' && s[i] <= 'f')
result[i] = (unsigned char)(s[i] - 'a') + 10;
else if (s[i] >= 'A' && s[i] <= 'F')
result[i] = (unsigned char)(s[i] - 'A') + 10;
else
return -1;
}
return (result[0] << 4) | result[1];
}
/*
* Decode an url-encoded string.
* Returns a newly allocated string on success or NULL on failure.
*/
static char *
urldecode(const char *src)
{
char *ret, *dst;
int ch;
ret = xmalloc(strlen(src) + 1);
for (dst = ret; *src != '\0'; src++) {
switch (*src) {
case '+':
*dst++ = ' ';
break;
case '%':
if (!isxdigit((unsigned char)src[1]) ||
!isxdigit((unsigned char)src[2]) ||
(ch = hexchar(src + 1)) == -1) {
free(ret);
return NULL;
}
*dst++ = ch;
src += 2;
break;
default:
*dst++ = *src;
break;
}
}
*dst = '\0';
return ret;
}
/*
* Parse an (scp|ssh|sftp)://[user@]host[:port][/path] URI.
* See https://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04
* Either user or path may be url-encoded (but not host or port).
* Caller must free returned user, host and path.
* Any of the pointer return arguments may be NULL (useful for syntax checking)
* but the scheme must always be specified.
* If user was not specified then *userp will be set to NULL.
* If port was not specified then *portp will be -1.
* If path was not specified then *pathp will be set to NULL.
* Returns 0 on success, 1 if non-uri/wrong scheme, -1 on error/invalid uri.
*/
int
parse_uri(const char *scheme, const char *uri, char **userp, char **hostp,
int *portp, char **pathp)
{
char *uridup, *cp, *tmp, ch;
char *user = NULL, *host = NULL, *path = NULL;
int port = -1, ret = -1;
size_t len;
len = strlen(scheme);
if (strncmp(uri, scheme, len) != 0 || strncmp(uri + len, "://", 3) != 0)
return 1;
uri += len + 3;
if (userp != NULL)
*userp = NULL;
if (hostp != NULL)
*hostp = NULL;
if (portp != NULL)
*portp = -1;
if (pathp != NULL)
*pathp = NULL;
uridup = tmp = xstrdup(uri);
/* Extract optional ssh-info (username + connection params) */
if ((cp = strchr(tmp, '@')) != NULL) {
char *delim;
*cp = '\0';
/* Extract username and connection params */
if ((delim = strchr(tmp, ';')) != NULL) {
/* Just ignore connection params for now */
*delim = '\0';
}
if (*tmp == '\0') {
/* Empty username */
goto out;
}
if ((user = urldecode(tmp)) == NULL)
goto out;
tmp = cp + 1;
}
/* Extract mandatory hostname */
if ((cp = hpdelim2(&tmp, &ch)) == NULL || *cp == '\0')
goto out;
host = xstrdup(cleanhostname(cp));
if (!valid_domain(host, 0, NULL))
goto out;
if (tmp != NULL && *tmp != '\0') {
if (ch == ':') {
/* Convert and verify port. */
if ((cp = strchr(tmp, '/')) != NULL)
*cp = '\0';
if ((port = a2port(tmp)) <= 0)
goto out;
tmp = cp ? cp + 1 : NULL;
}
if (tmp != NULL && *tmp != '\0') {
/* Extract optional path */
if ((path = urldecode(tmp)) == NULL)
goto out;
}
}
/* Success */
if (userp != NULL) {
*userp = user;
user = NULL;
}
if (hostp != NULL) {
*hostp = host;
host = NULL;
}
if (portp != NULL)
*portp = port;
if (pathp != NULL) {
*pathp = path;
path = NULL;
}
ret = 0;
out:
free(uridup);
free(user);
free(host);
free(path);
return ret;
}
/* function to assist building execv() arguments */
void
addargs(arglist *args, char *fmt, ...)
{
va_list ap;
char *cp;
u_int nalloc;
int r;
va_start(ap, fmt);
r = vasprintf(&cp, fmt, ap);
va_end(ap);
if (r == -1)
fatal("addargs: argument too long");
nalloc = args->nalloc;
if (args->list == NULL) {
nalloc = 32;
args->num = 0;
} else if (args->num+2 >= nalloc)
nalloc *= 2;
args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *));
args->nalloc = nalloc;
args->list[args->num++] = cp;
args->list[args->num] = NULL;
}
void
replacearg(arglist *args, u_int which, char *fmt, ...)
{
va_list ap;
char *cp;
int r;
va_start(ap, fmt);
r = vasprintf(&cp, fmt, ap);
va_end(ap);
if (r == -1)
fatal("replacearg: argument too long");
if (which >= args->num)
fatal("replacearg: tried to replace invalid arg %d >= %d",
which, args->num);
free(args->list[which]);
args->list[which] = cp;
}
void
freeargs(arglist *args)
{
u_int i;
if (args->list != NULL) {
for (i = 0; i < args->num; i++)
free(args->list[i]);
free(args->list);
args->nalloc = args->num = 0;
args->list = NULL;
}
}
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.
*/
char *
tilde_expand_filename(const char *filename, uid_t uid)
{
const char *path, *sep;
char user[128], *ret;
struct passwd *pw;
u_int len, slash;
if (*filename != '~')
return (xstrdup(filename));
filename++;
path = strchr(filename, '/');
if (path != NULL && path > filename) { /* ~user/path */
slash = path - filename;
if (slash > sizeof(user) - 1)
fatal("tilde_expand_filename: ~username too long");
memcpy(user, filename, slash);
user[slash] = '\0';
if ((pw = getpwnam(user)) == NULL)
fatal("tilde_expand_filename: No such user %s", user);
} else if ((pw = getpwuid(uid)) == NULL) /* ~/path */
fatal("tilde_expand_filename: No such uid %ld", (long)uid);
/* Make sure directory has a trailing '/' */
len = strlen(pw->pw_dir);
if (len == 0 || pw->pw_dir[len - 1] != '/')
sep = "/";
else
sep = "";
/* Skip leading '/' from specified path */
if (path != NULL)
filename = path + 1;
if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX)
fatal("tilde_expand_filename: Path too long");
return (ret);
}
/*
* Expand a string with a set of %[char] escapes. A number of escapes may be
* specified as (char *escape_chars, char *replacement) pairs. The list must
* be terminated by a NULL escape_char. Returns replaced string in memory
* allocated by xmalloc.
*/
char *
percent_expand(const char *string, ...)
{
#define EXPAND_MAX_KEYS 16
u_int num_keys, i, j;
struct {
const char *key;
const char *repl;
} keys[EXPAND_MAX_KEYS];
char buf[4096];
va_list ap;
/* Gather keys */
va_start(ap, string);
for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
keys[num_keys].key = va_arg(ap, char *);
if (keys[num_keys].key == NULL)
break;
keys[num_keys].repl = va_arg(ap, char *);
if (keys[num_keys].repl == NULL)
fatal("%s: NULL replacement", __func__);
}
if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
fatal("%s: too many keys", __func__);
va_end(ap);
/* Expand string */
*buf = '\0';
for (i = 0; *string != '\0'; string++) {
if (*string != '%') {
append:
buf[i++] = *string;
if (i >= sizeof(buf))
fatal("%s: string too long", __func__);
buf[i] = '\0';
continue;
}
string++;
/* %% case */
if (*string == '%')
goto append;
if (*string == '\0')
fatal("%s: invalid format", __func__);
for (j = 0; j < num_keys; j++) {
if (strchr(keys[j].key, *string) != NULL) {
i = strlcat(buf, keys[j].repl, sizeof(buf));
if (i >= sizeof(buf))
fatal("%s: string too long", __func__);
break;
}
}
if (j >= num_keys)
fatal("%s: unknown key %%%c", __func__, *string);
}
return (xstrdup(buf));
#undef EXPAND_MAX_KEYS
}
int
tun_open(int tun, int mode, char **ifname)
{
#if defined(CUSTOM_SYS_TUN_OPEN)
return (sys_tun_open(tun, mode, ifname));
#elif defined(SSH_TUN_OPENBSD)
struct ifreq ifr;
char name[100];
int fd = -1, sock;
const char *tunbase = "tun";
if (ifname != NULL)
*ifname = NULL;
if (mode == SSH_TUNMODE_ETHERNET)
tunbase = "tap";
/* Open the tunnel device */
if (tun <= SSH_TUNID_MAX) {
snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun);
fd = open(name, O_RDWR);
} else if (tun == SSH_TUNID_ANY) {
for (tun = 100; tun >= 0; tun--) {
snprintf(name, sizeof(name), "/dev/%s%d",
tunbase, tun);
if ((fd = open(name, O_RDWR)) >= 0)
break;
}
} else {
debug("%s: invalid tunnel %u", __func__, tun);
return -1;
}
if (fd < 0) {
debug("%s: %s open: %s", __func__, name, strerror(errno));
return -1;
}
debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
/* Bring interface up if it is not already */
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun);
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
goto failed;
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
debug("%s: get interface %s flags: %s", __func__,
ifr.ifr_name, strerror(errno));
goto failed;
}
if (!(ifr.ifr_flags & IFF_UP)) {
ifr.ifr_flags |= IFF_UP;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
debug("%s: activate interface %s: %s", __func__,
ifr.ifr_name, strerror(errno));
goto failed;
}
}
if (ifname != NULL)
*ifname = xstrdup(ifr.ifr_name);
close(sock);
return fd;
failed:
if (fd >= 0)
close(fd);
if (sock >= 0)
close(sock);
return -1;
#else
error("Tunnel interfaces are not supported on this platform");
return (-1);
#endif
}
void
sanitise_stdfd(void)
{
int nullfd, dupfd;
if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
fprintf(stderr, "Couldn't open /dev/null: %s\n",
strerror(errno));
exit(1);
}
while (++dupfd <= STDERR_FILENO) {
/* Only populate closed fds. */
if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) {
if (dup2(nullfd, dupfd) == -1) {
fprintf(stderr, "dup2: %s\n", strerror(errno));
exit(1);
}
}
}
if (nullfd > STDERR_FILENO)
close(nullfd);
}
char *
tohex(const void *vp, size_t l)
{
const u_char *p = (const u_char *)vp;
char b[3], *r;
size_t i, hl;
if (l > 65536)
return xstrdup("tohex: length > 65536");
hl = l * 2 + 1;
r = xcalloc(1, hl);
for (i = 0; i < l; i++) {
snprintf(b, sizeof(b), "%02x", p[i]);
strlcat(r, b, hl);
}
return (r);
}
u_int64_t
get_u64(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int64_t v;
v = (u_int64_t)p[0] << 56;
v |= (u_int64_t)p[1] << 48;
v |= (u_int64_t)p[2] << 40;
v |= (u_int64_t)p[3] << 32;
v |= (u_int64_t)p[4] << 24;
v |= (u_int64_t)p[5] << 16;
v |= (u_int64_t)p[6] << 8;
v |= (u_int64_t)p[7];
return (v);
}
u_int32_t
get_u32(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int32_t v;
v = (u_int32_t)p[0] << 24;
v |= (u_int32_t)p[1] << 16;
v |= (u_int32_t)p[2] << 8;
v |= (u_int32_t)p[3];
return (v);
}
u_int32_t
get_u32_le(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int32_t v;
v = (u_int32_t)p[0];
v |= (u_int32_t)p[1] << 8;
v |= (u_int32_t)p[2] << 16;
v |= (u_int32_t)p[3] << 24;
return (v);
}
u_int16_t
get_u16(const void *vp)
{
const u_char *p = (const u_char *)vp;
u_int16_t v;
v = (u_int16_t)p[0] << 8;
v |= (u_int16_t)p[1];
return (v);
}
void
put_u64(void *vp, u_int64_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)(v >> 56) & 0xff;
p[1] = (u_char)(v >> 48) & 0xff;
p[2] = (u_char)(v >> 40) & 0xff;
p[3] = (u_char)(v >> 32) & 0xff;
p[4] = (u_char)(v >> 24) & 0xff;
p[5] = (u_char)(v >> 16) & 0xff;
p[6] = (u_char)(v >> 8) & 0xff;
p[7] = (u_char)v & 0xff;
}
void
put_u32(void *vp, u_int32_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)(v >> 24) & 0xff;
p[1] = (u_char)(v >> 16) & 0xff;
p[2] = (u_char)(v >> 8) & 0xff;
p[3] = (u_char)v & 0xff;
}
void
put_u32_le(void *vp, u_int32_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)v & 0xff;
p[1] = (u_char)(v >> 8) & 0xff;
p[2] = (u_char)(v >> 16) & 0xff;
p[3] = (u_char)(v >> 24) & 0xff;
}
void
put_u16(void *vp, u_int16_t v)
{
u_char *p = (u_char *)vp;
p[0] = (u_char)(v >> 8) & 0xff;
p[1] = (u_char)v & 0xff;
}
void
ms_subtract_diff(struct timeval *start, int *ms)
{
struct timeval diff, finish;
monotime_tv(&finish);
timersub(&finish, start, &diff);
*ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
}
void
ms_to_timeval(struct timeval *tv, int ms)
{
if (ms < 0)
ms = 0;
tv->tv_sec = ms / 1000;
tv->tv_usec = (ms % 1000) * 1000;
}
void
monotime_ts(struct timespec *ts)
{
struct timeval tv;
#if defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_BOOTTIME) || \
defined(CLOCK_MONOTONIC) || defined(CLOCK_REALTIME))
static int gettime_failed = 0;
if (!gettime_failed) {
# ifdef CLOCK_BOOTTIME
if (clock_gettime(CLOCK_BOOTTIME, ts) == 0)
return;
# endif /* CLOCK_BOOTTIME */
# ifdef CLOCK_MONOTONIC
if (clock_gettime(CLOCK_MONOTONIC, ts) == 0)
return;
# endif /* CLOCK_MONOTONIC */
# ifdef CLOCK_REALTIME
/* Not monotonic, but we're almost out of options here. */
if (clock_gettime(CLOCK_REALTIME, ts) == 0)
return;
# endif /* CLOCK_REALTIME */
debug3("clock_gettime: %s", strerror(errno));
gettime_failed = 1;
}
#endif /* HAVE_CLOCK_GETTIME && (BOOTTIME || MONOTONIC || REALTIME) */
gettimeofday(&tv, NULL);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = (long)tv.tv_usec * 1000;
}
void
monotime_tv(struct timeval *tv)
{
struct timespec ts;
monotime_ts(&ts);
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
}
time_t
monotime(void)
{
struct timespec ts;
monotime_ts(&ts);
return ts.tv_sec;
}
double
monotime_double(void)
{
struct timespec ts;
monotime_ts(&ts);
return ts.tv_sec + ((double)ts.tv_nsec / 1000000000);
}
void
bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
{
bw->buflen = buflen;
bw->rate = kbps;
- bw->thresh = bw->rate;
+ bw->thresh = buflen;
bw->lamt = 0;
timerclear(&bw->bwstart);
timerclear(&bw->bwend);
-}
+}
/* Callback from read/write loop to insert bandwidth-limiting delays */
void
bandwidth_limit(struct bwlimit *bw, size_t read_len)
{
u_int64_t waitlen;
struct timespec ts, rm;
+ bw->lamt += read_len;
if (!timerisset(&bw->bwstart)) {
monotime_tv(&bw->bwstart);
return;
}
-
- bw->lamt += read_len;
if (bw->lamt < bw->thresh)
return;
monotime_tv(&bw->bwend);
timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
if (!timerisset(&bw->bwend))
return;
bw->lamt *= 8;
waitlen = (double)1000000L * bw->lamt / bw->rate;
bw->bwstart.tv_sec = waitlen / 1000000L;
bw->bwstart.tv_usec = waitlen % 1000000L;
if (timercmp(&bw->bwstart, &bw->bwend, >)) {
timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
/* Adjust the wait time */
if (bw->bwend.tv_sec) {
bw->thresh /= 2;
if (bw->thresh < bw->buflen / 4)
bw->thresh = bw->buflen / 4;
} else if (bw->bwend.tv_usec < 10000) {
bw->thresh *= 2;
if (bw->thresh > bw->buflen * 8)
bw->thresh = bw->buflen * 8;
}
TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
while (nanosleep(&ts, &rm) == -1) {
if (errno != EINTR)
break;
ts = rm;
}
}
bw->lamt = 0;
monotime_tv(&bw->bwstart);
}
/* Make a template filename for mk[sd]temp() */
void
mktemp_proto(char *s, size_t len)
{
const char *tmpdir;
int r;
if ((tmpdir = getenv("TMPDIR")) != NULL) {
r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
if (r > 0 && (size_t)r < len)
return;
}
r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
if (r < 0 || (size_t)r >= len)
fatal("%s: template string too short", __func__);
}
static const struct {
const char *name;
int value;
} ipqos[] = {
{ "none", INT_MAX }, /* can't use 0 here; that's CS0 */
{ "af11", IPTOS_DSCP_AF11 },
{ "af12", IPTOS_DSCP_AF12 },
{ "af13", IPTOS_DSCP_AF13 },
{ "af21", IPTOS_DSCP_AF21 },
{ "af22", IPTOS_DSCP_AF22 },
{ "af23", IPTOS_DSCP_AF23 },
{ "af31", IPTOS_DSCP_AF31 },
{ "af32", IPTOS_DSCP_AF32 },
{ "af33", IPTOS_DSCP_AF33 },
{ "af41", IPTOS_DSCP_AF41 },
{ "af42", IPTOS_DSCP_AF42 },
{ "af43", IPTOS_DSCP_AF43 },
{ "cs0", IPTOS_DSCP_CS0 },
{ "cs1", IPTOS_DSCP_CS1 },
{ "cs2", IPTOS_DSCP_CS2 },
{ "cs3", IPTOS_DSCP_CS3 },
{ "cs4", IPTOS_DSCP_CS4 },
{ "cs5", IPTOS_DSCP_CS5 },
{ "cs6", IPTOS_DSCP_CS6 },
{ "cs7", IPTOS_DSCP_CS7 },
{ "ef", IPTOS_DSCP_EF },
{ "lowdelay", IPTOS_LOWDELAY },
{ "throughput", IPTOS_THROUGHPUT },
{ "reliability", IPTOS_RELIABILITY },
{ NULL, -1 }
};
int
parse_ipqos(const char *cp)
{
u_int i;
char *ep;
long val;
if (cp == NULL)
return -1;
for (i = 0; ipqos[i].name != NULL; i++) {
if (strcasecmp(cp, ipqos[i].name) == 0)
return ipqos[i].value;
}
/* Try parsing as an integer */
val = strtol(cp, &ep, 0);
if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255)
return -1;
return val;
}
const char *
iptos2str(int iptos)
{
int i;
static char iptos_str[sizeof "0xff"];
for (i = 0; ipqos[i].name != NULL; i++) {
if (ipqos[i].value == iptos)
return ipqos[i].name;
}
snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos);
return iptos_str;
}
void
lowercase(char *s)
{
for (; *s; s++)
*s = tolower((u_char)*s);
}
int
unix_listener(const char *path, int backlog, int unlink_first)
{
struct sockaddr_un sunaddr;
int saved_errno, sock;
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
if (strlcpy(sunaddr.sun_path, path,
sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
error("%s: path \"%s\" too long for Unix domain socket",
__func__, path);
errno = ENAMETOOLONG;
return -1;
}
sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
saved_errno = errno;
error("%s: socket: %.100s", __func__, strerror(errno));
errno = saved_errno;
return -1;
}
if (unlink_first == 1) {
if (unlink(path) != 0 && errno != ENOENT)
error("unlink(%s): %.100s", path, strerror(errno));
}
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
saved_errno = errno;
error("%s: cannot bind to path %s: %s",
__func__, path, strerror(errno));
close(sock);
errno = saved_errno;
return -1;
}
if (listen(sock, backlog) < 0) {
saved_errno = errno;
error("%s: cannot listen on path %s: %s",
__func__, path, strerror(errno));
close(sock);
unlink(path);
errno = saved_errno;
return -1;
}
return sock;
}
void
sock_set_v6only(int s)
{
#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
int on = 1;
debug3("%s: set socket %d IPV6_V6ONLY", __func__, s);
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1)
error("setsockopt IPV6_V6ONLY: %s", strerror(errno));
#endif
}
/*
* Compares two strings that maybe be NULL. Returns non-zero if strings
* are both NULL or are identical, returns zero otherwise.
*/
static int
strcmp_maybe_null(const char *a, const char *b)
{
if ((a == NULL && b != NULL) || (a != NULL && b == NULL))
return 0;
if (a != NULL && strcmp(a, b) != 0)
return 0;
return 1;
}
/*
* Compare two forwards, returning non-zero if they are identical or
* zero otherwise.
*/
int
forward_equals(const struct Forward *a, const struct Forward *b)
{
if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0)
return 0;
if (a->listen_port != b->listen_port)
return 0;
if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0)
return 0;
if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0)
return 0;
if (a->connect_port != b->connect_port)
return 0;
if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0)
return 0;
/* allocated_port and handle are not checked */
return 1;
}
/* returns 1 if process is already daemonized, 0 otherwise */
int
daemonized(void)
{
int fd;
if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) {
close(fd);
return 0; /* have controlling terminal */
}
if (getppid() != 1)
return 0; /* parent is not init */
if (getsid(0) != getpid())
return 0; /* not session leader */
debug3("already daemonized");
return 1;
}
/*
* Splits 's' into an argument vector. Handles quoted string and basic
* escape characters (\\, \", \'). Caller must free the argument vector
* and its members.
*/
int
argv_split(const char *s, int *argcp, char ***argvp)
{
int r = SSH_ERR_INTERNAL_ERROR;
int argc = 0, quote, i, j;
char *arg, **argv = xcalloc(1, sizeof(*argv));
*argvp = NULL;
*argcp = 0;
for (i = 0; s[i] != '\0'; i++) {
/* Skip leading whitespace */
if (s[i] == ' ' || s[i] == '\t')
continue;
/* Start of a token */
quote = 0;
if (s[i] == '\\' &&
(s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
i++;
else if (s[i] == '\'' || s[i] == '"')
quote = s[i++];
argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
argv[argc] = NULL;
/* Copy the token in, removing escapes */
for (j = 0; s[i] != '\0'; i++) {
if (s[i] == '\\') {
if (s[i + 1] == '\'' ||
s[i + 1] == '\"' ||
s[i + 1] == '\\') {
i++; /* Skip '\' */
arg[j++] = s[i];
} else {
/* Unrecognised escape */
arg[j++] = s[i];
}
} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
break; /* done */
else if (quote != 0 && s[i] == quote)
break; /* done */
else
arg[j++] = s[i];
}
if (s[i] == '\0') {
if (quote != 0) {
/* Ran out of string looking for close quote */
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
break;
}
}
/* Success */
*argcp = argc;
*argvp = argv;
argc = 0;
argv = NULL;
r = 0;
out:
if (argc != 0 && argv != NULL) {
for (i = 0; i < argc; i++)
free(argv[i]);
free(argv);
}
return r;
}
/*
* Reassemble an argument vector into a string, quoting and escaping as
* necessary. Caller must free returned string.
*/
char *
argv_assemble(int argc, char **argv)
{
int i, j, ws, r;
char c, *ret;
struct sshbuf *buf, *arg;
if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
for (i = 0; i < argc; i++) {
ws = 0;
sshbuf_reset(arg);
for (j = 0; argv[i][j] != '\0'; j++) {
r = 0;
c = argv[i][j];
switch (c) {
case ' ':
case '\t':
ws = 1;
r = sshbuf_put_u8(arg, c);
break;
case '\\':
case '\'':
case '"':
if ((r = sshbuf_put_u8(arg, '\\')) != 0)
break;
/* FALLTHROUGH */
default:
r = sshbuf_put_u8(arg, c);
break;
}
if (r != 0)
fatal("%s: sshbuf_put_u8: %s",
__func__, ssh_err(r));
}
if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
(r = sshbuf_putb(buf, arg)) != 0 ||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
fatal("%s: malloc failed", __func__);
memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
ret[sshbuf_len(buf)] = '\0';
sshbuf_free(buf);
sshbuf_free(arg);
return ret;
}
/* Returns 0 if pid exited cleanly, non-zero otherwise */
int
exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet)
{
int status;
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR) {
error("%s: waitpid: %s", tag, strerror(errno));
return -1;
}
}
if (WIFSIGNALED(status)) {
error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status));
return -1;
} else if (WEXITSTATUS(status) != 0) {
do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
"%s %s failed, status %d", tag, cmd, WEXITSTATUS(status));
return -1;
}
return 0;
}
/*
* Check a given path for security. This is defined as all components
* of the path to the file must be owned by either the owner of
* of the file or root and no directories must be group or world writable.
*
* XXX Should any specific check be done for sym links ?
*
* Takes a file name, its stat information (preferably from fstat() to
* avoid races), the uid of the expected owner, their home directory and an
* error buffer plus max size as arguments.
*
* Returns 0 on success and -1 on failure
*/
int
safe_path(const char *name, struct stat *stp, const char *pw_dir,
uid_t uid, char *err, size_t errlen)
{
char buf[PATH_MAX], homedir[PATH_MAX];
char *cp;
int comparehome = 0;
struct stat st;
if (realpath(name, buf) == NULL) {
snprintf(err, errlen, "realpath %s failed: %s", name,
strerror(errno));
return -1;
}
if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
comparehome = 1;
if (!S_ISREG(stp->st_mode)) {
snprintf(err, errlen, "%s is not a regular file", buf);
return -1;
}
if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
(stp->st_mode & 022) != 0) {
snprintf(err, errlen, "bad ownership or modes for file %s",
buf);
return -1;
}
/* for each component of the canonical path, walking upwards */
for (;;) {
if ((cp = dirname(buf)) == NULL) {
snprintf(err, errlen, "dirname() failed");
return -1;
}
strlcpy(buf, cp, sizeof(buf));
if (stat(buf, &st) < 0 ||
(!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
(st.st_mode & 022) != 0) {
snprintf(err, errlen,
"bad ownership or modes for directory %s", buf);
return -1;
}
/* If are past the homedir then we can stop */
if (comparehome && strcmp(homedir, buf) == 0)
break;
/*
* dirname should always complete with a "/" path,
* but we can be paranoid and check for "." too
*/
if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0))
break;
}
return 0;
}
/*
* Version of safe_path() that accepts an open file descriptor to
* avoid races.
*
* Returns 0 on success and -1 on failure
*/
int
safe_path_fd(int fd, const char *file, struct passwd *pw,
char *err, size_t errlen)
{
struct stat st;
/* check the open file to avoid races */
if (fstat(fd, &st) < 0) {
snprintf(err, errlen, "cannot stat file %s: %s",
file, strerror(errno));
return -1;
}
return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
}
/*
* Sets the value of the given variable in the environment. If the variable
* already exists, its value is overridden.
*/
void
child_set_env(char ***envp, u_int *envsizep, const char *name,
const char *value)
{
char **env;
u_int envsize;
u_int i, namelen;
if (strchr(name, '=') != NULL) {
error("Invalid environment variable \"%.100s\"", name);
return;
}
/*
* If we're passed an uninitialized list, allocate a single null
* entry before continuing.
*/
if (*envp == NULL && *envsizep == 0) {
*envp = xmalloc(sizeof(char *));
*envp[0] = NULL;
*envsizep = 1;
}
/*
* Find the slot where the value should be stored. If the variable
* already exists, we reuse the slot; otherwise we append a new slot
* at the end of the array, expanding if necessary.
*/
env = *envp;
namelen = strlen(name);
for (i = 0; env[i]; i++)
if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
break;
if (env[i]) {
/* Reuse the slot. */
free(env[i]);
} else {
/* New variable. Expand if necessary. */
envsize = *envsizep;
if (i >= envsize - 1) {
if (envsize >= 1000)
fatal("child_set_env: too many env vars");
envsize += 50;
env = (*envp) = xreallocarray(env, envsize, sizeof(char *));
*envsizep = envsize;
}
/* Need to set the NULL pointer at end of array beyond the new slot. */
env[i + 1] = NULL;
}
/* Allocate space and format the variable in the appropriate slot. */
/* XXX xasprintf */
env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value);
}
/*
* Check and optionally lowercase a domain name, also removes trailing '.'
* Returns 1 on success and 0 on failure, storing an error message in errstr.
*/
int
valid_domain(char *name, int makelower, const char **errstr)
{
size_t i, l = strlen(name);
u_char c, last = '\0';
static char errbuf[256];
if (l == 0) {
strlcpy(errbuf, "empty domain name", sizeof(errbuf));
goto bad;
}
if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) {
snprintf(errbuf, sizeof(errbuf), "domain name \"%.100s\" "
"starts with invalid character", name);
goto bad;
}
for (i = 0; i < l; i++) {
c = tolower((u_char)name[i]);
if (makelower)
name[i] = (char)c;
if (last == '.' && c == '.') {
snprintf(errbuf, sizeof(errbuf), "domain name "
"\"%.100s\" contains consecutive separators", name);
goto bad;
}
if (c != '.' && c != '-' && !isalnum(c) &&
c != '_') /* technically invalid, but common */ {
snprintf(errbuf, sizeof(errbuf), "domain name "
"\"%.100s\" contains invalid characters", name);
goto bad;
}
last = c;
}
if (name[l - 1] == '.')
name[l - 1] = '\0';
if (errstr != NULL)
*errstr = NULL;
return 1;
bad:
if (errstr != NULL)
*errstr = errbuf;
return 0;
}
/*
* Verify that a environment variable name (not including initial '$') is
* valid; consisting of one or more alphanumeric or underscore characters only.
* Returns 1 on valid, 0 otherwise.
*/
int
valid_env_name(const char *name)
{
const char *cp;
if (name[0] == '\0')
return 0;
for (cp = name; *cp != '\0'; cp++) {
if (!isalnum((u_char)*cp) && *cp != '_')
return 0;
}
return 1;
}
const char *
atoi_err(const char *nptr, int *val)
{
const char *errstr = NULL;
long long num;
if (nptr == NULL || *nptr == '\0')
return "missing";
num = strtonum(nptr, 0, INT_MAX, &errstr);
if (errstr == NULL)
*val = (int)num;
return errstr;
}
int
parse_absolute_time(const char *s, uint64_t *tp)
{
struct tm tm;
time_t tt;
char buf[32], *fmt;
*tp = 0;
/*
* POSIX strptime says "The application shall ensure that there
* is white-space or other non-alphanumeric characters between
* any two conversion specifications" so arrange things this way.
*/
switch (strlen(s)) {
case 8: /* YYYYMMDD */
fmt = "%Y-%m-%d";
snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
break;
case 12: /* YYYYMMDDHHMM */
fmt = "%Y-%m-%dT%H:%M";
snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s",
s, s + 4, s + 6, s + 8, s + 10);
break;
case 14: /* YYYYMMDDHHMMSS */
fmt = "%Y-%m-%dT%H:%M:%S";
snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s",
s, s + 4, s + 6, s + 8, s + 10, s + 12);
break;
default:
return SSH_ERR_INVALID_FORMAT;
}
memset(&tm, 0, sizeof(tm));
if (strptime(buf, fmt, &tm) == NULL)
return SSH_ERR_INVALID_FORMAT;
if ((tt = mktime(&tm)) < 0)
return SSH_ERR_INVALID_FORMAT;
/* success */
*tp = (uint64_t)tt;
return 0;
}
void
format_absolute_time(uint64_t t, char *buf, size_t len)
{
time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */
struct tm tm;
localtime_r(&tt, &tm);
strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
}
+
+/* check if path is absolute */
+int
+path_absolute(const char *path)
+{
+ return (*path == '/') ? 1 : 0;
+}
diff --git a/misc.h b/misc.h
index 31b207a8d9d9..5b4325aba2b8 100644
--- a/misc.h
+++ b/misc.h
@@ -1,175 +1,182 @@
-/* $OpenBSD: misc.h,v 1.75 2018/10/03 06:38:35 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.79 2019/01/23 21:50:56 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef _MISC_H
#define _MISC_H
#include <sys/time.h>
#include <sys/types.h>
+#include <sys/socket.h>
/* Data structure for representing a forwarding request. */
struct Forward {
char *listen_host; /* Host (address) to listen on. */
int listen_port; /* Port to forward. */
char *listen_path; /* Path to bind domain socket. */
char *connect_host; /* Host to connect. */
int connect_port; /* Port to connect on connect_host. */
char *connect_path; /* Path to connect domain socket. */
int allocated_port; /* Dynamically allocated listen port */
int handle; /* Handle for dynamic listen ports */
};
int forward_equals(const struct Forward *, const struct Forward *);
int daemonized(void);
/* Common server and client forwarding options. */
struct ForwardOptions {
int gateway_ports; /* Allow remote connects to forwarded ports. */
mode_t streamlocal_bind_mask; /* umask for streamlocal binds */
int streamlocal_bind_unlink; /* unlink socket before bind */
};
/* misc.c */
char *chop(char *);
char *strdelim(char **);
char *strdelimw(char **);
int set_nonblock(int);
int unset_nonblock(int);
void set_nodelay(int);
int set_reuseaddr(int);
char *get_rdomain(int);
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 a2tun(const char *, int *);
char *put_host_port(const char *, u_short);
+char *hpdelim2(char **, char *);
char *hpdelim(char **);
char *cleanhostname(char *);
char *colon(char *);
int parse_user_host_path(const char *, char **, char **, char **);
int parse_user_host_port(const char *, char **, char **, int *);
int parse_uri(const char *, const char *, char **, char **, int *, char **);
long convtime(const char *);
char *tilde_expand_filename(const char *, uid_t);
char *percent_expand(const char *, ...) __attribute__((__sentinel__));
char *tohex(const void *, size_t);
void sanitise_stdfd(void);
void ms_subtract_diff(struct timeval *, int *);
void ms_to_timeval(struct timeval *, int);
void monotime_ts(struct timespec *);
void monotime_tv(struct timeval *);
time_t monotime(void);
double monotime_double(void);
void lowercase(char *s);
int unix_listener(const char *, int, int);
int valid_domain(char *, int, const char **);
int valid_env_name(const char *);
const char *atoi_err(const char *, int *);
int parse_absolute_time(const char *, uint64_t *);
void format_absolute_time(uint64_t, char *, size_t);
+int path_absolute(const char *);
void sock_set_v6only(int);
struct passwd *pwcopy(struct passwd *);
const char *ssh_gai_strerror(int);
typedef struct arglist arglist;
struct arglist {
char **list;
u_int num;
u_int nalloc;
};
void addargs(arglist *, char *, ...)
__attribute__((format(printf, 2, 3)));
void replacearg(arglist *, u_int, char *, ...)
__attribute__((format(printf, 3, 4)));
void freeargs(arglist *);
int tun_open(int, int, char **);
/* Common definitions for ssh tunnel device forwarding */
#define SSH_TUNMODE_NO 0x00
#define SSH_TUNMODE_POINTOPOINT 0x01
#define SSH_TUNMODE_ETHERNET 0x02
#define SSH_TUNMODE_DEFAULT SSH_TUNMODE_POINTOPOINT
#define SSH_TUNMODE_YES (SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET)
#define SSH_TUNID_ANY 0x7fffffff
#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
/* Fake port to indicate that host field is really a path. */
#define PORT_STREAMLOCAL -2
/* Functions to extract or store big-endian words of various sizes */
u_int64_t get_u64(const void *)
__attribute__((__bounded__( __minbytes__, 1, 8)));
u_int32_t get_u32(const void *)
__attribute__((__bounded__( __minbytes__, 1, 4)));
u_int16_t get_u16(const void *)
__attribute__((__bounded__( __minbytes__, 1, 2)));
void put_u64(void *, u_int64_t)
__attribute__((__bounded__( __minbytes__, 1, 8)));
void put_u32(void *, u_int32_t)
__attribute__((__bounded__( __minbytes__, 1, 4)));
void put_u16(void *, u_int16_t)
__attribute__((__bounded__( __minbytes__, 1, 2)));
/* Little-endian store/load, used by umac.c */
u_int32_t get_u32_le(const void *)
__attribute__((__bounded__(__minbytes__, 1, 4)));
void put_u32_le(void *, u_int32_t)
__attribute__((__bounded__(__minbytes__, 1, 4)));
struct bwlimit {
size_t buflen;
- u_int64_t rate, thresh, lamt;
+ u_int64_t rate; /* desired rate in kbit/s */
+ u_int64_t thresh; /* threshold after which we'll check timers */
+ u_int64_t lamt; /* amount written in last timer interval */
struct timeval bwstart, bwend;
};
void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t);
void bandwidth_limit(struct bwlimit *, size_t);
int parse_ipqos(const char *);
const char *iptos2str(int);
void mktemp_proto(char *, size_t);
void child_set_env(char ***envp, u_int *envsizep, const char *name,
const char *value);
int argv_split(const char *, int *, char ***);
char *argv_assemble(int, char **argv);
int exited_cleanly(pid_t, const char *, const char *, int);
struct stat;
int safe_path(const char *, struct stat *, const char *, uid_t,
char *, size_t);
int safe_path_fd(int, const char *, struct passwd *,
char *err, size_t errlen);
/* readpass.c */
#define RP_ECHO 0x0001
#define RP_ALLOW_STDIN 0x0002
#define RP_ALLOW_EOF 0x0004
#define RP_USE_ASKPASS 0x0008
char *read_passphrase(const char *, int);
int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
#endif /* _MISC_H */
diff --git a/moduli b/moduli
index 372c382a270c..4c694736119b 100644
--- a/moduli
+++ b/moduli
@@ -1,428 +1,452 @@
-# $OpenBSD: moduli,v 1.22 2018/09/20 08:07:03 dtucker Exp $
+# $OpenBSD: moduli,v 1.23 2018/10/31 11:20:04 dtucker Exp $
# Time Type Tests Tries Size Generator Modulus
-20180403031539 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A591E4B57
-20180403031604 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5923D0DB
-20180403031626 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A592B11B7
-20180403031845 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A59715A73
-20180403032143 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A59CDE963
-20180403032347 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5A11B463
-20180403032438 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5A2BBC5F
-20180403032617 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5A6308C3
-20180403032923 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5ADA5523
-20180403033405 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5B9A6B37
-20180403033427 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5B9F8E27
-20180403033655 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5C00897F
-20180403033742 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5C172DBB
-20180403033837 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5C33AEAB
-20180403033952 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5C5F6067
-20180403034409 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5CEE2AD7
-20180403034453 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5CFFE4F3
-20180403034601 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5D1A691B
-20180403035311 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5E04B193
-20180403035645 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5E75D66F
-20180403035724 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5E864847
-20180403035828 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5EA44DCF
-20180403035953 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5ECCB51B
-20180403040048 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5EE55A9F
-20180403040339 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5F4D5E6F
-20180403040523 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5F8939A3
-20180403040638 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5FB85E8B
-20180403040715 2 6 100 2047 2 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A5FCC3033
-20180403041128 2 6 100 2047 5 F78A3F3A47AFE34101F186DF022B970FB51586E65B1D1875E41D02EDDD4BDF6D6D8BA1CC296EA6A8BD7036297A0C01C636A55493E3ADEC2F1DAB9D8D7E0CCD39D7FFC9D4011C3F57A944AA1EEB1AC1784E28ACF7B6FB3AC49185F4E638B567DA6B4903CB8C6D815ED1253D512670FAF71E6BF1ED6669863B552B3BB2173A7F16262454142B7B928F91E60EED00BDFA465F2C46665BD30C1426F9B8D9611D086D6BAB672CB472E8F8E6990F623C2E7458991D982E199BB168C93F96F71974181F898D6C56C02D9DABA852E7E51CA0DC723255B49CAA122D2A6CC64F1389128A0E3298B0E155EC8A4D9BF1D1671B808DDD835015381C1F16C35A84D20A60755C57
-20180403041637 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336541B76F
-20180403041935 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3365BF1D13
-20180403042035 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3365E41E47
-20180403042109 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3365F700BB
-20180403042214 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336624FF2B
-20180403042419 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336687845B
-20180403042507 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3366A8266B
-20180403042626 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3366E23603
-20180403042722 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3367059073
-20180403042819 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3367289EC3
-20180403042928 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3367519D23
-20180403042946 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336758BFC3
-20180403043032 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336774A8EB
-20180403043218 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3367BAAE3F
-20180403043245 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3367C6B5CB
-20180403043522 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3368340BB3
-20180403043954 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B33690CEBC3
-20180403044107 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B33693DA563
-20180403044245 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B33697A63FB
-20180403044527 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B3369F3CAFF
-20180403044559 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336A09E6EB
-20180403044611 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336A0C4F53
-20180403044719 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336A4348BF
-20180403044820 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336A6E3193
-20180403044844 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336A7A9C7F
-20180403045235 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336B2E2173
-20180403045518 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336BAD847B
-20180403045629 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336BE29A4B
-20180403045953 2 6 100 2047 2 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336C865153
-20180403050042 2 6 100 2047 5 EA0303D03FF69BCABDC25DDEA6AC9CFEE8C36EF48C7F2882B65D568B0D14A7DACCF4A6E8E905727C0B982FA4D7C4E59DDAF4704D0EC767D79B13A32467C8D39F615B5268E4338DD70C6072C702CDF6F39153C472E668ABF0B85B8D08454027AA52E3227C5BA017B2558F7A611F09C7BE5E28A472FAB51C71FF7E8C758CD5205C562F3674D941EF2DEC7F3B3F49C4CE3A9DD7B4275BD537BF04A4A8E98FAA42AD0A2280CFC0D4692339EEC803B69FDC33057837FBD233DB6B78920F7049B5F9CA9CFDD98351B9E7947265439F48429306D6CAB08774F2B7427A61DA757375D26C08B99BCAFB8085E41DBA0E49D142EEC164CC3153AB3119FB76033B336CA6948F
-20180403055314 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57012EEDBB
-20180403055637 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57015FFFAB
-20180403060753 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57021C5763
-20180403061035 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570243FBBB
-20180403061925 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5702CE55A3
-20180403062241 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5702FA4263
-20180403062828 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5703495AD7
-20180403063232 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570383322F
-20180403063441 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57039D0EE7
-20180403065803 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5704F5DFCB
-20180403070250 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570535A157
-20180403071043 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5705AD5B2B
-20180403072237 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57066B3AFF
-20180403072347 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5706763D5B
-20180403072612 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570696B733
-20180403073322 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5707062E2B
-20180403073825 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5707547607
-20180403073948 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570762843F
-20180403074104 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57076EC3DB
-20180403074403 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570799DD63
-20180403074828 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5707D93973
-20180403075240 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570814F21B
-20180403075918 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570878D0DB
-20180403080045 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5708890F47
-20180403080212 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570898D8B3
-20180403080523 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5708C1E14B
-20180403080854 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5708EEE0AF
-20180403081003 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5708F7F537
-20180403081710 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570961D7DB
-20180403082007 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570988E91B
-20180403082804 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570A02958B
-20180403084609 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570B1FC24F
-20180403084705 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570B262033
-20180403084905 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570B3DD5AB
-20180403085348 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570B82B95B
-20180403090858 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570C6C2E5F
-20180403091014 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570C766563
-20180403092356 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570D49B077
-20180403092842 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570D8D7FEB
-20180403093424 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570DE274D7
-20180403093850 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570E28C2BB
-20180403094634 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570EA36EDF
-20180403094738 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570EACDABB
-20180403095906 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B570F67B813
-20180403101909 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5710AFC157
-20180403102057 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5710C6E1FB
-20180403102257 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5710DF2FD7
-20180403102711 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57111EFB2F
-20180403104106 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5711F3B14F
-20180403104411 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B5712188817
-20180403104503 2 6 100 3071 5 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57121EA02F
-20180403104712 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57123CDA13
-20180403104901 2 6 100 3071 2 FF8DCF143A9E3CC447F8D3D03206E386572BFAC54F4BDE233C8B1223CC9CBA99689328E35F8F83F0922A9F0AB33E7C7892E940377CE0064700ECDCC8532F0FEF888913E1894054707878511DD84455BEACCA35E8418D6CAD03111BC1842581D40E280A13055030CB35339E2A0E422DB9EC47916AD6302BE248AD5EBCCE7CF087CB2285A6B8D227DC7130ADB14163BE4D1AA779DBCD36710AA080F219B535B1887392DE9EF44116C933F5CA2234A7A82A8A48F1691A39434D70E3C3995AEE7CEAFF86DAA2326CF367B7E3C7939E4B78A00EE58E52F7BB36C8A89525CA4D44173E30AA6B40FD0B60C29F6CBC763241AC5DA16E2A9FB9B78F360EED32704B686AD6D40DAE8127C9351A2B21C140292E77592A7159000FB2AA9561DA10B2AC3167CC8E41C10CDF86E9041A3A114F42EF4AA5134C716893E81C3A7488ED5131073FC76B20358549BF1B0858B571550663DA9CF73B7B28BF9CA1FAF8EC96966D493C174B03DBCF9B5470DD9A79FB3E14A0B73B6E6C09D531886ACF60E51B57125332B3
-20180403105756 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE03762997
-20180403111214 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0468815B
-20180403111819 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE04C53C43
-20180403111907 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE04CAC50F
-20180403112635 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0540031F
-20180403113403 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE05B956F7
-20180403113943 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0619B7F3
-20180403114045 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE06220B07
-20180403114120 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0622E517
-20180403115211 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE06D363E7
-20180403115424 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE06F22507
-20180403115558 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE070516F3
-20180403115753 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE071E3297
-20180403115927 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0731011F
-20180403121723 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE085D2303
-20180403122312 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE08B88A7F
-20180403123158 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE09563C53
-20180403123328 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0969A18F
-20180403123534 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE09876D27
-20180403124247 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE09F3F4CF
-20180403124446 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0A10443F
-20180403125400 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0AA6560F
-20180403131328 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0BF05873
-20180403131708 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0C28FCF3
-20180403132618 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0CC05D43
-20180403140905 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE0FBCA05B
-20180403141813 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE1054C7EF
-20180403143434 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE1176152B
-20180403143933 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE11C90E93
-20180403144751 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE125A12D3
-20180403145406 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE12C4F6CF
-20180403145448 2 6 100 3071 5 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE12CA246F
-20180403145549 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE12D582AB
-20180403150132 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE13386F43
-20180403150512 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE1373A2CB
-20180403150605 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE137CA7DB
-20180403151404 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE140AEF53
-20180403152834 2 6 100 3071 2 D9FA0132FCCAAE8116BD22861CD21A859841BA7D566829E10ACC15A7EFEEB381774F839F7228AE3C627F5765944DCDB6866618E187903EBDB558C9186BD84D2521630A379E161FDCEC19BA02A8E4B5A3C4A66D02CA0FEB7BEB75BA3BE87F26BB99122217A4FFEB1F730B430AA0A70BA4A91EFB248DF689E95957E93B9E5D2AC13FBD3896759F77C6CBB6664BA6FEB31C4FD7BF081D4F2D800AB8D979D89A5EFB34675A904F4B332ADD7340116E7D5D4F72F7E3940A30036ACA889C27D8E2E11C0668A2E8A43DFF411FA03F0AFB420262947A60528805A7E0F4B2CC6AC0EF62CBCB807BC131A8D51E7784A13C77DB461A9FDF01C0E97EA8B7C5A13BB4A86784C2FFA34FC1EF094ACB858A919951AA55508E468CBB889EA63B606D45455AAB75883A75A813E9EC6A3A49CADB05A62C2F5CA32013A4FC73E8B5DE1C14A39539A4716B157C08C74CD99EA23AE018A89C838B6C0EAEECDFCF78A447594033ED3D63F4623BFC05C0F6701A36420D60D9C99339F9486395CBE534D66CE66AAE14BB5263
-20180403164629 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445F2ACFC43
-20180403173943 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445F45D568B
-20180403183028 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445F603359B
-20180403183423 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445F61BDC27
-20180403194550 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445F877D863
-20180403202122 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445F9A0304B
-20180403210313 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445FAFCEC73
-20180403213851 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445FC2F80FF
-20180403215353 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445FCA8B737
-20180403222440 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445FDAD53EF
-20180403224035 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445FE2EF2E3
-20180403224214 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D445FE343553
-20180403234157 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446002B2C0F
-20180404012449 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446038F5C77
-20180404012740 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446039F760B
-20180404013701 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D44603E742CF
-20180404024209 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4460610756B
-20180404034850 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446083DCDA7
-20180404035100 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446084796E3
-20180404035224 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446084ACD8B
-20180404040621 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D44608BABFE3
-20180404043706 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D44609B60613
-20180404044213 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D44609DB5067
-20180404050247 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4460A8585C3
-20180404053546 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4460B94238B
-20180404054127 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4460BBC6C0B
-20180404060250 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4460C67CBB7
-20180404061330 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4460CA93683
-20180404084828 2 6 100 4095 2 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D446115943A3
-20180404085435 2 6 100 4095 5 D6A36D53FE335EAC6C6F21F2963EEF44BF055FBE1D529CAC77341CADF25097607135D53FBDF5ED5B3BB2CE243834E344600627AB46C3F3952C0E59AAD95A13E0B299073FA6C02260432090C66B7DFA4C06633B8D31E7376024958AEF0B57A6A1519DC39CCFD65E33B19DA7C52C0C6DA0E5990A5DCDE9CB16C36408E6CC825FA464EC6CF3848202E6197281C8176600BEAABAB5E2C0598A97C9A5AC7606A0583DFFBD20FA424D1B62E0E5FAF7DA56C1CEB3C309C999C5B574322B8E511BA14342DAA24EA688E16B05CFC6B89696FF17BF21EC5AF75FB3A6258E6EA4CEE93B06299FC2D32441238B8EBF78124347A0E56522079641D5CB6F8858A91F9C7B1047E7CFCF6A80A0884BE39E9FB8CACE70865A022E538E80C899A43E5842C753E8332A8972249E4EAEB2C327FCD2777488CD9A1F03A242889D3F33A5C5047721605727486E3B97F3BEC6D8BF7C7B4512FB6AC8B854BD92B0ECC9F65408254BDDD8428F0F68EEF4FC61F033C56FF65C566B81994C1B92308771151DEBE7C814C608F99B784251C1CC4E5F110F5D9B9104BC8D60544FC4955204EF21F429E3D618C10F5F3A178BD71CEFD02ADF8AA5A3B79EB2038BC31467EE98AD1EA501B492EEF950B5B3E95AD0D792B585E3F6164E6B5EC52701DE13B6C7D832D339618E4C7372F8D02E48E743FB7477FDF8ED746987F72F4FFD46F1CEEA5340ABFC82D4461181EE57
-20180404093010 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B396361597
-20180404100034 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3973953BB
-20180404112136 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B399EA8DDF
-20180404112714 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B39A1427A3
-20180404115040 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B39AD94553
-20180404130727 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B39D6ABE8B
-20180404132841 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B39E19247F
-20180404140647 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B39F5CFEAB
-20180404144308 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A087B8A7
-20180404154403 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A271BD2F
-20180404155315 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A2B7E4DF
-20180404164237 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A451FC23
-20180404165126 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A494B437
-20180404172833 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A5C78E83
-20180404175448 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A6A037D3
-20180404183147 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A7D443E3
-20180404183316 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A7D883F3
-20180404190024 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3A8B7BF5F
-20180404194132 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AA11DC3B
-20180404195020 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AA5664E3
-20180404195123 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AA56EAF3
-20180404202233 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AB5A9C37
-20180404202802 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AB8229D3
-20180404203244 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3ABA0DD8B
-20180404203913 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3ABCF8F47
-20180404210704 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3ACB6CB0B
-20180404213123 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AD7FE977
-20180404223506 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3AF9772FB
-20180404225041 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B016049F
-20180404225753 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B04C3C37
-20180404230652 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B092364B
-20180404231941 2 6 100 4095 5 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B0F7D807
-20180404232637 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B127CC5B
-20180404233306 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B154E443
-20180405003707 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B373FAF3
-20180405012137 2 6 100 4095 2 C287DA1692C8760D889CABEA6A7055FADB13C9F064C87322D569B9C574001DEBA1685DA8DFFB9A11253F685A3045E2CEBA057C35DD417F717110949007702B25A37AEE60C3A1A9AA6A1667C15BBFFFF173DF27813A74959756822AB34A2BB97B2F408CC6A994ADC83F05CB8028784B859A25032D691F1DDFB1A87F47EDC289FE4452BE4E4D7B07745C1D5A901E7EF0521465DFFC1EECAB7E4F15172A90257AFFCA11B455ADD24067B20C20EDF9B5B59BDFDAE03BF0AB39A13E60515CA8ADE3273BBCA8290D3B581F92B61F1A893ABFF16255A9226638159640F7869B5C30C8FFF3C3378B14E1A5529C8DE120A9E2099388E1217BDDFCC1708F37E74BDE5D0A2DCFDC4DD27BA697C3F8238182DA7C5D02431E086067358CC9A9B4EFF7C8D7FC9F0C8C0528887A194A6D0613AEE1EEDDC7A315AC1A178E9377E488F49367573BA8EDF80FD6EDE2D256F0614AF81B8FB1B243EA7F04CA6BE0E0BE9F43525D3B6718DAA5E2FD3D20BE3F37ED402DAFD7F19C39E51A40868D3F79D45CD422A9F7454DB3FEFF205BE4C10234914FD8882B344DBFB5C2BE5B576EA94EB62C3AFCD012EE7F82F0744BE067736E9A78EF38E6F06474E025776F138AF84E4093AB36683A60D0DB5CB9F75CA7C4303059E0DDCE3A641A3278F5015FD42EAA79B72E5F0D2EFDAADE3B76B23DD4C2A39F359B3CA00F7584B729800B3E01DC3D4CD4B3B4E4FE3B
-20180405071813 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436983FC590B
-20180405072141 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436983FCDA2F
-20180405132535 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043698806F173
-20180405133926 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436988262AB7
-20180405165648 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043698A47BC0B
-20180405195101 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043698C28BB2F
-20180405213026 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043698D395FBB
-20180405220015 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043698D843327
-20180405231702 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043698E544067
-20180406025336 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436990AEC063
-20180406035121 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043699149227B
-20180406063935 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436992C6FC43
-20180406115213 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436995ACE13F
-20180406155248 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436997C8EA27
-20180406170431 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D595320436998593AD3
-20180406184640 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043699940ADB7
-20180407000748 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043699C562CCB
-20180407041558 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D59532043699EECE453
-20180407070330 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A0B1D577
-20180407100408 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A29D405B
-20180407103952 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A2F83A33
-20180407123940 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A43ACBEB
-20180407154812 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A62F48B7
-20180407170835 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A704C5AF
-20180407175007 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A76C88B7
-20180407184438 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A7F65E03
-20180407195743 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369A8B41617
-20180408071229 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369AFC7905B
-20180408075553 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369B03562E7
-20180408124736 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369B3416E27
-20180408125929 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369B35942B3
-20180409023705 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369BBCCDCBB
-20180409072217 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369BEB6303F
-20180409124237 2 6 100 6143 2 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369C1F95DB3
-20180409150941 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369C3A97BA7
-20180409162805 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369C56C92A7
-20180409185627 2 6 100 6143 5 E0CFB3582CE2D136E662908DCAA4CD666F574807FFFFF04BFB357D087BD132C8B569A579EC7FEDA39DA9FDBC7A8B289953FC1793F1B5D0F13A317C5F25554892D8A4F4EE9E85B9737D1412316C8169810745D8AC420ED45AA5419137F86E811AA101CD8746EDC5AF653499CA5585851205807E7EC4A3241FDD4C302AAC131FE24B2AC3700D3D21A82EB999FD0005E810811CEB2B1279D95E028269503DBF65FB23CBFC595B12BC67EC4A77D00324909088B6FDF511ABA41732957D32CC436FB0BE95E04F46DF57EC93E4FBD8FF12E18288384CBFABB1BD58F4A047CBF1AB831B43C550515DA98CA33697ECEE8AFAC110E7DD284D531324AC21013C86CFBC9DC286B6669534D8E2D40319E9BA9DC5ACE1825354E1869614CBCB708586A9455D20FC3B724C6FBF941EAAB3FFA61647906B890D9C8F2831A59B7A9A4EB6305DAEDE94A0525C8150EA3B27FC405430B82885E8EAA64A46E2E24DA089A0008C09C5B8117F5E5F397DCAC43906067AE2C6A1B7C1D1B2D233EFF6CBC472F328053EB666EC826604ADA4E27CA01FF98B7A5ADCF8FD3A6E2F6AEC4F36CE8D1D847E611CFDDA7B53AE4F0BA6481A2265D134B5B78F8416164B262CF58FA8806090613D09FA2E8CC417AF2A3208F5BB210CA87927C4FB980C9B97A743CC1B3A7BB9E22DD78EDFB52669C4DB24F796C5D99038E140CE81A9DFECE675F200DC0DEC203FB94380EAA8D13F30530A410BCBD393137FBF89AB80D872D6A4A46B303F01E79FA05DEF4F0F2A2ABD0788459E4C678F3952072570971EA5A686E5964D1C3A61E2311F57E7AB8519809243EB88A87A21B6589A16862EE1B9B4DD452950DDBB5D5482099FC667B5F9A43E3F803D9D0030D0D6E0F86DBFD2B0C2A67B9BFB1F318C6DF0745F75F9F59C7CC62F4763FBBFE3517BF28D9B68372674CBB759E150F6F06FB3053343D54DB7959B79C3764FE57AC25EF6728F1A6A2C6D98E56841DC461BBF12BD23E8C058D500435777431ADC23CA373B0F4A43B5E18787925E79113199A368F30692429BF3041D9BC82BFF88147C3DE432169578E304C72D5953204369C8DC8A0F
-20180409201511 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E047122A7
-20180409212042 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E06189297
-20180410021123 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E0D35B28F
-20180410022638 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E0D8CA623
-20180410024637 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E0E02E03F
-20180410063306 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E1393582B
-20180410063848 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E13B0682B
-20180410071153 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E147AB73B
-20180410082253 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E16363257
-20180410101335 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E18F03B13
-20180410105609 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E19F1DE37
-20180410152104 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E205A4ACB
-20180410153733 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E20B2606F
-20180410175655 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E240655BF
-20180410204830 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E281EDA87
-20180410231426 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E2B95718B
-20180410233438 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E2C0621C7
-20180410234833 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E2C5297E3
-20180411035657 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E32375BE3
-20180411053901 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3499E12F
-20180411073150 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3738967B
-20180411073910 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E375B7807
-20180411075734 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E37C0C66B
-20180411081855 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E383A5BCB
-20180411093848 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3A0D60EB
-20180411094657 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3A351317
-20180411110541 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3C08A7A7
-20180411120731 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3D6EB9BB
-20180411130125 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E3EAD50F3
-20180411151653 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E41CC6D9F
-20180411152943 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E4210423B
-20180411184911 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E46A13843
-20180411191726 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E473E26CF
-20180411205712 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E498A1853
-20180411212652 2 6 100 6143 5 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E4A2D607F
-20180411215657 2 6 100 6143 2 E01FFD7EC91328929E4FD6183C9C9EDF4EF8CFC608D943A1011CEE0B49D7322663D64028F7205A4F008A0C8F393F91FF42D1C7ACB6B4041D0DC79BB0DA6D394532A0E33BC96FEA6EC2E67987F13D2F218B9E8A46D20125D822B6AA1C9615087E5C667CCA74414305E3382E20792B058F61D9DBFD93EF80A2E30E17FDB883F79989B540A6E467D9CEF07C849B659890706CAC7FF6F95669DAD0D9170D485C298AA940C6B7B3092E265FB512C70F36E3D6515B7B799E20FFE9DA35F932C3F2C238F5D8BCB92193216563D6163EB9FAAFEDD0E8A1A3F8CE292E8A1BEF630C5E75D845444B414017844E9560C8309CD54BF9EEAB2CAAE888226AB8031F1569A728256BB6FCC14DF314314F9F2DF75E781E8A4A5411ACCB4D9E3103131F52E0D14386A6E107AA7A522E42F1A41C8A8E46CE69E824492B87BC8B34A457EC25A7508B3E1A33BCC9E99EA754163AEC31161A83A80780DF46D36E757CF90C0F002DF73AB406F7DF81FDA75AD7F3F052EEA91955FA737616D8D4BB87A60FF471400D50688146BC3C10FF60A35D8BB9EF6BEF26497361118125FBEE607726AA408674A45931C87666146BE520503A5241D49B964406A864749C50F9B2718B8E0F62614DB27F35F53D57F70CB4ECE081BD377CDBA5C4AD75BEA63CB8E2653E52D11C0CAC67916B0C24232FC9D90091C7CDD317D4F60D8271D81E70B79031BE25CD5D6CC1E7A04FAF98C25B143B9D7B08D94160B1737AB49F55A01AF3A9BB7C8C261E8F2F84A1995C752276F5F03E54EE22A973F63C73083377DD6851634AA5568AA1173E5BE96606D946AAC82951E326750E18C2AD12C311EF784AD9014BEE322032B45244BD6EEDA224CCDA93983C8FB326F8C8B02F5574B0BC0CD7BFD1C524CD66ACD8A7AC1619E57136F2FEB5F49E9791D4E0F0C9AB8B9E7A98E49E5603D4E02771EFC9993ED15974CD0EEA50510C410FD884CB5D83D0FCD0AF7218D49523F95C4C396CBC0359DABD75EC138910788E1766649130AD089F565ED926B4F26FEBAF9CA4F768E6CA6E6BB7E43769B7D46E2F0D6A63254B41715567635FC1D38DCD7E4AD99963
-20180412095549 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D1E908A07
-20180412222127 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D28C808CB
-20180413014812 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D2B32FFD3
-20180413033600 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D2C8AD64F
-20180413142737 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D34F03213
-20180413150907 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D35714FEF
-20180413164654 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D36BB8D1B
-20180413202724 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D39A4E13B
-20180413203949 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D39C6A4FB
-20180413211909 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D3A44F883
-20180414010718 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D3D3D3257
-20180414125221 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D467C1523
-20180414181319 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D4AA2837B
-20180414202910 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D4C60657F
-20180414210359 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D4CCB3D87
-20180415054313 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D53659F57
-20180415133017 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D596ABEFF
-20180415160204 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D5B5415B7
-20180415222232 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D6018A3AB
-20180415224834 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D6064EF13
-20180416005338 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D61F17307
-20180416021119 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D62E1D04F
-20180416083930 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D67B78127
-20180416182014 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D6EDFEF6B
-20180416190916 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D6F71FA97
-20180416195012 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D6FE60F77
-20180417005002 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D737F03EF
-20180417031611 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D75497E7B
-20180417042601 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D761E7D7F
-20180417230051 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D83ABCCEF
-20180417231044 2 6 100 7679 5 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D83C22B2F
-20180418011858 2 6 100 7679 2 FBED7F3DD7CF86B0A6EEDC1930C6958C3C00695DAF4347560C5AC1AA4B22F4DC76F190D63E230EB0CB4344A370A471F17FFCA8DA3B5B0A903F9D1258370125F6C172F3EC5F56D7B8EBD07B2072C45D6141DA3CDC01C3D95DE279C5FAA1E042651028141085EB68AFAC473600F75F4A373DC234D5405DCE7AB5B5854960ABC550FCEFEE8FD578810201DE6B4A5EF616F0CBF5707466D7ECBFD488EB68AD4B2EAC889BA2B7FEFE19CD8AA2C78F61D5DA08B4BC2738E1997F951A525EEF9F668148996D1ABFD1620F9276D741A46BECC0B7868A54745E0B16589A4AA7B938AF92FCA0FC9BBC193504D7EBFEFFEC996746DC6CAD3C192D724FB51E6228915789FF18314B3EB690359ADED802F35F48EC0D9C85AA1A20A2E5CF6EB795F2CCD03284547688B1B80A07EFC31668D30836C59C958BBBF6C1EE3940CC43A9334289C872302BB70368FDAC1653AF132F3E398E9310159C839E72555FD889E4E3B05E714E44E116804BF3748F62EF46E6A05DEC58A55185E43E2310EC945004AD61945BD2AD923B7B3C69A01C0393C15B6000BF542A55274ACA20B8A6EB96FAF83E27023FE0EA9EE564959A91BE17110176FB10D1A094947A23EFDE15DD093EF477EF798BCA8F5E14F85411242BC9C9492081444490C072BE8511B3C961AAAC80477897B54BDABE78C533F2E149FA64B51936E31F126625566CAFBB57E9F36CE0DF72A45E61AB27B6D25DEA3BA35910E16BB00AD300CEE2535CE75F9411DD43943250B03EBBA60C5C788974F2F695967103045F3A90A587AEFD0613F9C8E10A273DD827A314C75C7DBCE4326191DBCB92020CDB75129BCA032B6FD59D368C3E2404B2832398E40F43ACE284A91DED8812AA23E5B5A1D36AE204C53F1C6EF0E89AD31D1552E70538451847D7332D8FCACB62A1E56C1E5643E4F7AF63C67E082AC95DCB190795FA53522FA046F1919C81A088D7A8A452124E562BE2A702139670E94524D3110B9DFF35AE73F43280600B8304FA2E776089AF2ED929695967998E29A343FF62C4CAD7618222C01735734342FD33284BE9BDA4976DA1BC3B384E6F813FCBDFA3DC57B841515836CB2B37116EB6D417BBE6AEA7604AA915530AD803DF1C13656753C1A5867F4A3AE94BA7347580EE5A6CEBD2F3EB9B7F83E7B74F38995168F08A15A4CDF5702EA9DC907FC45910586D59537582DB1D5F155BF0050866CE3087560F1F44D1F275FD2B422038F9D8643C3BEBA49938D514848AC4F68F4CF44329C7E806B911B0CB7FF0020F3277A3E2B4FF17090D012B641E24D67A962E2FE361504DB014155F074F30F52078CB31DFC51B32746A42EDBF013F9920CFB17D8545B2B3
-20180418054538 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA00823770B
-20180418071157 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA00950BDC3
-20180418085254 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA00AAFBDDB
-20180418174929 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA01225DA53
-20180418210652 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA014D6E5DF
-20180418211238 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA014E1D75B
-20180418224228 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA016133603
-20180418233547 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA016C53D1F
-20180419053435 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA01B7B0413
-20180419055744 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA01BC212DB
-20180419135850 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA022362F53
-20180419162659 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA02429C813
-20180419214419 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA0286020EF
-20180420033054 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA02CE157FF
-20180420033355 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA02CE22F0F
-20180420131137 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA03463D903
-20180420174655 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA037E8E853
-20180420224816 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA03BC5BAEB
-20180421002804 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA03CFF8483
-20180421033707 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA03F5CEF07
-20180421044121 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA04029ED83
-20180421054539 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA040F07753
-20180421080206 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA042A70927
-20180421084346 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA04323E033
-20180421135101 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA04708373F
-20180421220150 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA04D33A023
-20180421233337 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA04E52D9FF
-20180422094542 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA055FBBC03
-20180422151643 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA05A0B8E53
-20180422163933 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA05B02DF5B
-20180423004105 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA060EDD493
-20180423045850 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA06410777F
-20180423175352 2 6 100 7679 2 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA06D85A5C3
-20180424034739 2 6 100 7679 5 ECCC9B93ED119552D36A774B288F541A81536A13B8D687B23174D680CE3F21B8FA088685F5B965215AFA69736E741A3AFC2AC82CE16162A1E4F0012F28998A638AA98D0789D6C58D92F207EAAA33E467C801891B8D37651B66E0942CF6AB7FD8E0D09A6D597D582BA48563F1450C3300218874730D26EE8B6505059C95C1C764D5FD736BF0A64FAD10F0C7D52A8A57C3FBD653887AAA890DA7AFEDA55DAF702EFF06CC722D147DAA2C8B78F0707F51D2B326BEF8972F5A289829E998B94D98E0ED663143797B569F3A6B56897B5726A38B042806FDFDAA367A4F63C4BA31114300B6290828321C30B25DF97F273041E30A404836E84BB32E0620DC558047FC011A1205126F84D9F8EA5E607FC297E5C9FA00D803026D8126C08EF68B49F6A6C55DCB06EED0B666880CD49FCBFF598055D5E40303669CBC55D85F583DA5EF4F320D6E6A50ECBBFAF8C1F7209655EEAA58BFC18EB9FA20B29EC63FBC810C3A2EDCF8E27FD98975C87D59D9C909895AA10CEA5F7594ADD3ED1EBDFE01BE0559423475592A0E2936E4671504337221F897AE3016BC4670C6B765F5FF1185933B26B1183BCB1E5591970F40A1402EB19EF2644E941F67ABB31935259308B4A5271541F41653EB5E77CCA82214C9C6F4E42E8A3C46CC9BE15BC868BC45B28027E515A16554B9D4F6AB57CFFE42CFE0B42BF83E53F27B39AD95E000C329F716E51D15D6CD211E87AAA83A0F1175F5E1E8963A57DA656FBC19FB42661F14328B05CA7F1A83F49044A5086E6AF56225B8783450E43CB1B6F19061441AF58053BBFAACBC3A80FF5F19A8BD873F487A8FFE3DECD35E77EB2C26387EF66A3EED98C773211914115AFD0776FDAC90CB65479DFE59C0D199F195BBE9E4B2F70A9B1A41429002C2998FAB0F2D6956731819D9F5175B92FECE43178BC69ABEC6E2C18EA88289C5B14C58227640D02F614A9A881633816B9DCAC79E4721EF6E42691902AD1CF565600BAA8019310CAA0AC1087A86846C2E9B96B82C3F0CE52EE73760111061EF090DCBF47882710302A65FBDCF380F84703FE3D4FF7ADD0CB7ED65C889DD6EEC24D01F92771DF3F3D8DFB4BDE234D4A35AB20B22BF5D749398C9B6AE5C7B62DC11ACD887A49586238F5B6D37B47EA6953C3E339A9B40EF3EB01DD70F69253BA9A262777C75DF175195D172BD8233FC7B6F207154EF6E2F47533E359D24EB312A292C756C34A2D55A16452829DAD7A9731E2026E56486F6A3C07380DCA1AFFF270464DA8FF34621FBA715C5853EB1D4EA1C4E23B43CD1CDE1F252B728875F187626A813B4166CC34A62A5D6867E0B605641CEE8025F0AD73DBE4443286CA074B2314F
-20180424155916 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFACFC9C07
-20180424222331 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFB180A887
-20180425154127 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFBD59073B
-20180426001519 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFC3391D93
-20180426011753 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFC3E66CFF
-20180426121313 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFCB4C31C7
-20180426192735 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFD02C1487
-20180427041246 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFD60EF383
-20180427102113 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFD9FE975B
-20180427110709 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFDA77CFC7
-20180427115833 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFDB032A8F
-20180427231209 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFE24BAFE7
-20180428032748 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFE509AE73
-20180428050334 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFE60622B3
-20180428204832 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF035C75F
-20180428220506 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF0FF9743
-20180428221212 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF108842F
-20180429040829 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF4BDEDDF
-20180429045604 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF5372357
-20180429052346 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF57C9113
-20180429053535 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6CFF591B0F3
-20180429234833 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D000DBC47B
-20180430061137 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D004DD4873
-20180430071004 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D0056DDF9F
-20180430074559 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D005C5181B
-20180430091811 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D006B26D17
-20180430191732 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D00CD17013
-20180501005739 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D01047BA13
-20180501022059 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D01117B47B
-20180501025617 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D0116B88A7
-20180501031400 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D01190866F
-20180501201356 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D01BDDAB3B
-20180501204003 2 6 100 8191 5 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D01C18942F
-20180502033416 2 6 100 8191 2 FAEE1044985A5E9005F621D69401F45F006C4AC70C849E5C17F3D28A22FE2C86DEF3780E73C15BC778C65638702E1DF6193E19C79BC8A9CEC1D64759E6E8E1B3754AAD1F82819BDB1F1E224F7D7BFF62061D89F6AE8D8EAF444A543333A4E71A4EBEE16AA9FEAE434FD965B90E6B57A198C12619CC31EF4F2BA3ACEA4C0D31EDD7BD715FE76FCD9282221F27F6CFD678ABC0458E4EDFBB72FB23333A3137C1C9AEB0AE4E5D98148527A5670311C0181861C1305901FF9704C64F88B75AD76574ABE3B5CEAAC2F675F5A56B807B2D9FFEDC975C7CFC6C697A18ED7F3D76C164FE108255F43971A3CCEE8FDC5E95F38B6ED8F8B150E17A7780E2D5CFD9A4D35BC4E2B3C3F4F286DC9DD0A8A53A22E643AD29753AAAB58E4C268A4145B1958050895F7FF5EB300FD0435824024F6DA4C38039A621D8E553493D964479DB2C1647C5123A9ED27955117CB966D41BAB3FA2F6AE1CE0E9787E3C815B1E3A3E3002B0BC54A89D66A3B532E8152BB0FD681D134374B4F2197F0B451E4C68C589E1F213D42CB62FC749D0883D9A68B39B93A1582F957AC989E5664266BB53BB8A07C84F662D5E3B4D4B277840A98B37F8A2CDF892085AF77A0AD370B2A4649F2381B7136AEB189421C6C801DC4F20273922A57C76DB4DB487DFC33DA2AC490C77E8ABA4AC719E6F0428A37ADBBE04F776199ACE29C1BC3B8A1F8E0D049628FDA016735559589D660FB23421D29745528E160F60B5D1923E685D0E04BE9DAC15C90BCAC4F4A7FD5CE52950734F2A849CAAB083DD18324EE82D1679146E60C290A97E2C94FBFEEDD88DE9EBEB346DF9E11AE14F4540A84F98B210E5366A03A82128986543C48FC3867431B2531AF99B379CE7E8D3105C574B0D4974295E98EFA2C01AC31C80CB1654BCEFA8467A55BC7B55ADB92DC1BE438006E5392ED521B5817558DE5E38172D023E3236EEAE34037E92EA61D6DA463212E012E603709D65EBE8062644A17B1A00FF5DE6E42FD4B3812DACC8C85754616A5539AB60FEF0F9170413E94D3052CBA3A7B9FCF46F318D30DD88DD988C9C16F5BB8823538A8DBC4830B00E7CE5346277E4DAD464128025955E7E5FD184C40EEC184B6143FC4720DA45C7DE3ED4849D6ABC89B1C01D6761660EA595B65E7F70457A32A4D63CCC6FC9736ABDDB9AE9FC8FB90388DAB7BD2189B38488B17DA76B96DAB6871475F59FC36BD53076293EBF9970A1081BA84E44A3A109F6B7231E64C1C54BF9AABD2320185DC054672B2F8F52172CD262F14CCA3237542F421A2413DF5E371DD4F1297E01D81E392A6C4F3BBABAA3091B2F10DB1C4A2C12B0DDDC279F7AD45992225ACA55ADA7CB6370B07B0CD5B935B8DF18BFFA2567EBF77658772D043318B6BA159DBD3AA48C7A509A1F887A05118CBE1470599C2683D9C00DAA5480A05FFDDF7612E6D02024C2DB
-20180502214537 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED639CFC883
-20180503020255 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED63CD06DCB
-20180503022319 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED63D0368DF
-20180503125648 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6446836FF
-20180503155809 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED64679B30F
-20180503191156 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED648AEA87F
-20180504050354 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED64F75441F
-20180504071143 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED650DC49F3
-20180504084722 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED651F00D33
-20180504103430 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED65316D0B7
-20180504105453 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED65348CDBB
-20180504234946 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED65BF5CBBF
-20180505042813 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED65F0A04E7
-20180505043446 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED65F133337
-20180505082348 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6618FACC3
-20180505142452 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED665916E9B
-20180505191845 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED668B9BE0B
-20180506011717 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED66CA10377
-20180506064643 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED67028E243
-20180506091931 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED671CB9597
-20180506094237 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED67201565B
-20180506200807 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED678BDEA8B
-20180507012051 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED67C15F093
-20180507102714 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED681E510A7
-20180507105523 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6822806B3
-20180507204038 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6885CE023
-20180508025258 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED68C4A13A7
-20180508064503 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED68EAB2CC7
-20180508094511 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED69078137B
-20180509200633 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6A5AB6E77
-20180509233450 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6A7C34C7F
-20180510003712 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6A85E2007
-20180510011010 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6A8ABBDA3
-20180510075358 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6AC65344B
-20180510102028 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6ADD74BF3
-20180510111207 2 6 100 8191 2 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6AE56234B
-20180510122304 2 6 100 8191 5 E3FCBDCFD41A409C58BE083B6485A2D67E20931B1F469774BAE0F1AB2898B800032581B1C4FC71FE136087937A885AFB6FC9E582DD97B8DE3AD2AF861419D5F06278316DFA78BAE7EF099889F0E99575C7812E7240B67623E7877737013A7D5DB3638040083400E8F27600BAC0650D24220CA1B3C05FB7DD70469A201DBFF1308ECA1C7152A6016BB89BFB6C625715EE91A92EA1848F0B2491AA92187468D9E8442679D7F5F6B64BC9D5A3D4E9B58C59EEEB65F8D6B70A71099E1B420BC0FD750CB2F333C23C97966BE727A6B6D9AEC8C0EB2436E01770F03840BFEC9228BB6DD46CE27D5739E18429F464FFF6812B0F66A8B0024BE03294900B8D0BC3CA6785F8C418EFE7068B2CD190A54BB9F90E05885A5C85DC069495C2009F79DBFD7774D7D65B9831FDC295CE146F4EB91DC56ABBD0B64BEAF3C340E0BF123A115D12289D44B650FF8461734308F4701CF2C199676DB3B4804FCDBD6B08C5D4875073AD5C575CA0B64597472A5C23EB4277B52B1128F3B1AE363E36A2C2D6EF5FCE00EE1573A40AD5ACDCDADE3E2672979CF68E87530520B2CA2C1110CBE4B631F3ABE83CFFDB7D5ACDD6DCA5916E30B1771FE29C4F60163B62349B66C0EDDCE8502F7C49DD4089EA5AE31FFB220A88C8D232367B52FAB7644F02E7EC10378697213CF0D90DA83A9941C217C559F88DEC6587AD953C95F11C575F0EFA9CC0650955C733910F2F90C78AE367F67B0F496A100E0B018731404D2BAEC7420F8C2B1FB6612AF69ECF369F236DD0BFB0ACBAED4141B2A14591C6475FC5C3D4E9B6229ECF7E288C015D59A35DE67F633DC586609AB3AB85A02B99DDF1B6FA7D54D4B2DDB767CAAB797C9FB29594B80B5BAACF777666D0B35CE6EFD8E46270C4D715B74FEA64FE34FBF4332BB4E8477CA438645C24444417EA5769B507925FB4B8FC59E429F1EC593C397F71087A080B39A192B5147D04D9F30DC237764C810E519B74EE90F047D0829104B6BA1A01F1CC18C85BE79F52084FAD6D7BF3EDA36D63981D8B75676740DB1AA6E06AD0C1F6A3B665D2D9D0E363FCE37B581C682A5F554D820849CEE7066A7DB011EA7D916B4A45212CBBC7A56ADAD33D203B8A1EDA03064A34351916C243E65D45425974C1468A626B773B48962108203F02814F15640149BCC2325C40F2457F0618CAAFDE26162326F2F81E8C727FAFED1B43E3AC8752E9F4EDFF5B58BD316882B555E63278FEB00B61144703C060B6188F3528E176E9B2D5996579048B723EB678CD56FA979004270E9F88F235404C522ED076E9F287097F2F7600A2D4566D2F6EFB600A9854B61CDB4363040D4F30D96BB011EF4BB0E0F21192F72B106B4F38A79FA384978C3C2A9AB94534BE01C83927BC95A9C5E55E618D7C5D77A9FA39664EEF11B2D50F59396DAD7CDC23F17948585BD88342EED6AF06789F
+20180920083436 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0BE8103
+20180920083444 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0C7C3CF
+20180920083448 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0C8204B
+20180920083506 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0E7A6DB
+20180920083516 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0F5096B
+20180920083532 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE11027BF
+20180920083549 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE12EA013
+20180920083601 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE13F42E7
+20180920083617 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE15AA2C3
+20180920083643 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE18AB6BB
+20180920083714 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE1C69837
+20180920083747 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE207143B
+20180920083825 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE24E3977
+20180920083852 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2843EE7
+20180920083857 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE285908B
+20180920083917 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2A7511B
+20180920083924 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2B08EBF
+20180920083936 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2C326CF
+20180920083953 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2E0BCBB
+20180920084017 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE30D862B
+20180920084034 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE32AADEF
+20180920084040 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE32F8FDB
+20180920084114 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE372E443
+20180920084154 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE3C3748F
+20180920084236 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4158847
+20180920084247 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4262F2F
+20180920084310 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE452029F
+20180920084323 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE467FAEB
+20180920084353 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4A3A77B
+20180920084435 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4F4FEC3
+20180920084446 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE50404F3
+20180920084451 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE50889BB
+20180920084547 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE57A3D23
+20180920084627 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE5CC4913
+20180920084636 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE5D944FB
+20180920084649 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE5EF41F7
+20180920084732 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE646894F
+20180920084755 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE670C3B7
+20180920084818 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE69AD617
+20180920084821 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE69AE223
+20180920084833 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE6ADE1B3
+20180920084844 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE6BD0ACF
+20180920085036 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7ACC18B
+20180920085043 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7B37CAB
+20180920085052 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7BF34CF
+20180920085121 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7F719A3
+20180920085126 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7F7A70F
+20180920085132 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7FD3383
+20180920085137 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7FF6C03
+20180920085143 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE806800F
+20180920085147 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE807F56B
+20180920085153 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE80BD7DF
+20180920085205 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE81F7F6F
+20180920085257 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE88D9BB7
+20180920085403 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD79F990A17
+20180920085428 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD79FC4B55B
+20180920085452 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD79FF25EFF
+20180920085519 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0250433
+20180920085620 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0A900D3
+20180920085639 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0C7B767
+20180920085651 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0DB38C3
+20180920085658 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0E45E73
+20180920085744 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A13B7883
+20180920085800 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A155F0FF
+20180920085834 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A19802C3
+20180920085838 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A198FC0B
+20180920085854 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A1B38723
+20180920085908 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A1CBBC3F
+20180920090009 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A24638B7
+20180920090031 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A26FE49F
+20180920090036 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A272126F
+20180920090057 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2962B0B
+20180920090107 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2A69E27
+20180920090148 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2F49F9B
+20180920090155 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2FC98C7
+20180920090222 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A32E8983
+20180920090227 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A332034B
+20180920090238 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A341BC13
+20180920090357 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A3E82A8B
+20180920090414 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A405F593
+20180920090443 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A44029BB
+20180920090533 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A4A62F13
+20180920090600 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A4D96A23
+20180920090616 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A4F1B05B
+20180920090637 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5184683
+20180920090705 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A549FBCF
+20180920090716 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5593157
+20180920090727 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5681F87
+20180920090741 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A57EC4B3
+20180920090828 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5DD04FF
+20180920090834 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5E3B3D7
+20180920090935 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A660A94F
+20180920091000 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A68FC267
+20180920094201 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11528E4B7
+20180920094613 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B115D90A53
+20180920094828 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B116301C17
+20180920094842 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11631DCAF
+20180920095300 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B116E4CA3B
+20180920095312 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B116E4E133
+20180920095413 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B117068663
+20180920095436 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1170E270F
+20180920100204 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1184656D3
+20180920100341 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11883D577
+20180920100505 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B118B728DB
+20180920100550 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B118D00F87
+20180920100609 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B118D567E7
+20180920100942 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1196905F7
+20180920101027 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11980B233
+20180920101047 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B119877CCB
+20180920101204 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B119B78FAF
+20180920101600 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11A5CA257
+20180920102200 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11B5728B7
+20180920102235 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11B698D4F
+20180920102336 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11B8BE2EF
+20180920102711 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11C1D39BB
+20180920102826 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11C4B4083
+20180920103322 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11D1356A7
+20180920103630 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11D93FB63
+20180920103932 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11E0CAEBB
+20180920104303 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11E9CB9E3
+20180920104717 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11F4E4B63
+20180920104816 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11F72025B
+20180920105139 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11FFAA343
+20180920105211 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B120087713
+20180920105407 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B12052E023
+20180920105834 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1210F24F7
+20180920110033 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1215A8893
+20180920110055 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B12161A467
+20180920111239 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1234E3F83
+20180920111553 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B123D4E7B7
+20180920113107 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BD211E4B
+20180920113301 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BD69A2F3
+20180920113601 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BDE3D567
+20180920113838 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BE4DA06B
+20180920114445 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BF499357
+20180920114933 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C00F4FE3
+20180920115406 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C0C7C2CF
+20180920115734 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C159195F
+20180920120001 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C1B99ABF
+20180920120514 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C29330EB
+20180920120628 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C2C100E7
+20180920120657 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C2CD60CF
+20180920120944 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C33CEF4F
+20180920121341 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C3E0892F
+20180920121628 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C44E0077
+20180920121700 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C45D1D9F
+20180920121822 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C493C143
+20180920122041 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C4EF9D0B
+20180920122429 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C5898C03
+20180920122505 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C59B843B
+20180920122536 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C5A94107
+20180920122806 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C60D5BBB
+20180920123304 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C6DD0793
+20180920123753 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C7A1DB4B
+20180920124152 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C842B8B7
+20180920124601 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C8EEDABB
+20180920124906 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C96EA9B7
+20180920125743 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CAE0E013
+20180920125855 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CB0BFEAB
+20180920125915 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CB10BF07
+20180920130235 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CB9812B3
+20180920130731 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CC62B69B
+20180920130910 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CC9EFAAB
+20180920131150 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD0A69F7
+20180920131303 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD357E3F
+20180920131355 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD51C05F
+20180920131419 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD5A0C83
+20180920131529 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD82F3D3
+20180920134626 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1925064B
+20180920135427 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A19BA1E2B
+20180920141147 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1B0331C7
+20180920145454 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1E40577F
+20180920150140 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1EBA2BA3
+20180920161629 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A24551BC7
+20180920163144 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A256E6A8B
+20180920164626 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A26848667
+20180920164921 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A26B3187F
+20180920165252 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A26EC656B
+20180920165723 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A273A8833
+20180920170336 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A27A959BF
+20180920170729 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A27EBBC83
+20180920171833 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A28B88307
+20180920173958 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2A47E5BF
+20180920174751 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2AD76CDB
+20180920175337 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2B3F16FF
+20180920180736 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2C416607
+20180920181108 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2C7C62CF
+20180920182003 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2D1C8377
+20180920183639 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2E532EF7
+20180920185506 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2FAEF903
+20180920190842 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A30A680FB
+20180920193433 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A328D6FAB
+20180920193735 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A32BD423F
+20180920194925 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A339269AB
+20180920200058 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A34692BDB
+20180920200225 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A347B8EFF
+20180920200812 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A34DFF2BB
+20180920202050 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A35C67F5F
+20180920204239 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A3758AE93
+20180920204648 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A379DD5F3
+20180920212404 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C3B843C3
+20180920212755 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C3FC854F
+20180920213937 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C4D5B923
+20180920214830 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C578D833
+20180920215602 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C60301F7
+20180920222334 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C80CD293
+20180920223427 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C8D7E023
+20180920224739 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C9CDF40F
+20180920224953 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C9EF64FB
+20180920225400 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CA3777C7
+20180920225652 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CA6853C3
+20180920230359 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CAE81C2F
+20180920233313 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CD0FC883
+20180920233505 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CD297D7B
+20180920234143 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CDA00627
+20180920235433 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CE8651DF
+20180920235640 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CEA46B8F
+20180921000133 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CEFBF913
+20180921001904 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D039AC1B
+20180921002105 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D0557A5B
+20180921003739 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D184F8BB
+20180921004140 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D1C803A3
+20180921004415 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D1F094A7
+20180921004716 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D21F8203
+20180921005129 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D268646B
+20180921010446 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D3556B5B
+20180921013214 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D556768F
+20180921014417 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D62CB7EF
+20180921021218 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D835583B
+20180921023434 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D9D786F3
+20180921024155 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DA550ABB
+20180921031006 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DC5EBE23
+20180921031034 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DC5EC45F
+20180921032220 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DD2F3B53
+20180921032554 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DD68BE4B
+20180921032729 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DD7D755B
+20180921034633 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DED7E937
+20180921035421 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DF60EDC7
+20180921035905 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DFAC40E3
+20180921041542 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002E0D7FD93
+20180921042022 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002E12169CB
+20180921053713 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC509A2DF
+20180921055252 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC560A423
+20180921065744 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC6F28D1F
+20180921071557 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC75F93C3
+20180921113009 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4ACDA5C3BF
+20180921133701 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD0A30BD7
+20180921151331 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD2DFFEAB
+20180921154930 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD3B43EF3
+20180921162910 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD4A147DB
+20180921183414 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD79B0197
+20180921184903 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD7F055F3
+20180921190227 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD837F15B
+20180922004824 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AE097172B
+20180922040435 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AE5403DDB
+20180922052522 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AE71BA84B
+20180922073622 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEA2D28E3
+20180922084529 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEBD11737
+20180922095510 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AED6CB613
+20180922100442 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEDA11D23
+20180922102739 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEE243617
+20180922111522 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEF3698BF
+20180922122645 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF0DFB873
+20180922135149 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF2D2C0A3
+20180922135535 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF2DFCAFB
+20180922143740 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF3D211A3
+20180922150118 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF45675DB
+20180922161720 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF614E323
+20180922174324 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF80E023F
+20180922183959 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF956439F
+20180922202104 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFBAC649B
+20180922210150 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFC958F53
+20180922213354 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFD502EE3
+20180922232002 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFFC84A6B
+20180923014322 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B031123EB
+20180923030251 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B04EC8B2B
+20180923042422 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B06C56A47
+20180923075109 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B0B7BA467
+20180923091429 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1949920F8B
+20180923122354 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB194E3CB3E3
+20180923132927 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB194FD1CDE7
+20180923135953 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB195089F093
+20180923141725 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1950F052F7
+20180923153745 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1952DF5333
+20180923161625 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1953CC5B37
+20180923174651 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1955FDACA3
+20180923174907 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB195602AE57
+20180923185706 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1957A5593B
+20180923201932 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1959A6D687
+20180924141921 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1973A572FF
+20180924142936 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1973D9C983
+20180924143229 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1973E18163
+20180924144304 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19741666EB
+20180924164032 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1976CE68FB
+20180924164811 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1976F40FA7
+20180924172248 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1977BCD9FB
+20180924193420 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197ACC31C7
+20180924195813 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197B54F0A3
+20180924213953 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197DA923D7
+20180924220006 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197E18BC83
+20180924221925 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197E83B0E7
+20180924230442 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197F8509D7
+20180925002733 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB198168A38B
+20180925022629 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19842450D7
+20180925032318 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19856CA53F
+20180925033018 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19858EBEEB
+20180925033504 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1985A24167
+20180925040411 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19864B479F
+20180925075729 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB198B9EEEC3
+20180925083607 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB198C77AA37
+20180925142730 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416C2EDFD4B
+20180926003216 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416CB3AFEA3
+20180926041318 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416CE37F7FB
+20180926074350 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D109F343
+20180926090735 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D2224817
+20180926125425 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D526B7D3
+20180926162303 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D7F88093
+20180926165118 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D85194CB
+20180926224609 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DD089B0F
+20180926225812 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DD2A3B6B
+20180927013355 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DF3A214F
+20180927022646 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DFE1C77F
+20180927025105 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E02B64E3
+20180927073721 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E3F7C30F
+20180927091345 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E533987B
+20180927094940 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E5A3AA83
+20180927172504 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416EB936ECF
+20180927221028 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416EF491CEF
+20180928031538 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F33826BF
+20180928061816 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F58E9E8B
+20180928065908 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F6069543
+20180928120844 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F9FC5BCB
+20180928170131 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416FDB2EF23
+20180928221854 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B41701B64E6B
+20180929042224 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B417064EC2FF
+20180929093251 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170A2F02DB
+20180929124700 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170C92055B
+20180929125705 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170CA966AF
+20180929140557 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170D7B99EB
+20180929225234 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171409B02B
+20180930030835 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B417172F0403
+20180930110353 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171D11BFBF
+20180930124634 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171E461903
+20180930150219 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171FE2013B
+20181001021616 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4172812EAEB
+20181001072125 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4172BC07FE7
+20181001133408 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B41730368927
+20181002022928 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4608E66C77
+20181002041648 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C460A539D5F
+20181002080547 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C460D765A73
+20181002132925 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4611D8F2D7
+20181002195913 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C46170D027F
+20181003044410 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C461E0FB427
+20181003045243 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C461E245A3F
+20181003065635 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C461FC358AF
+20181003081458 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4620C4118B
+20181003091804 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4621936EAF
+20181003093652 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4621C96C57
+20181003213125 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C462B2BBD5B
+20181004064641 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4632523CCF
+20181004083341 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4633A72497
+20181004113212 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4635EC630B
+20181004123633 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4636B93337
+20181004144119 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C463844D7C3
+20181005025309 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4641A155C7
+20181005044622 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C46430AFEB3
+20181005053156 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464390BAB3
+20181005074342 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464535BB4B
+20181005094350 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4646B220EF
+20181005154803 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464B3844E3
+20181005164416 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464BE2332F
+20181005203233 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464EAB7A73
+20181006030808 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C46538BEADB
+20181006045927 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4654E5E903
+20181006134442 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465B551BBB
+20181006162315 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465D3CDE9F
+20181006171548 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465DD9203F
+20181006173731 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465E163313
+20181006214027 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C466102759F
+20181007065411 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4667A72DC3
+20181007123656 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C466BB5F597
+20181007145027 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C466D436643
+20181007184043 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C467005CF4B
+20181007223658 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211133D9A97
+20181008074149 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21119A92B8B
+20181008163451 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2111FD14FAB
+20181008224318 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211241066AB
+20181009003245 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211254A0343
+20181009070543 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21129CA56FB
+20181009111433 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2112C8E0D93
+20181009152706 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2112F6601C7
+20181009164722 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2113048398B
+20181009203858 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21132D1168F
+20181010040332 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21137C65BFB
+20181011070638 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21149914247
+20181011150252 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2114EAE7D3B
+20181011153554 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2114EFEE58B
+20181011234311 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211542C97AF
+20181012043844 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21157397D47
+20181012060434 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115803DB63
+20181012142459 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115CF3077F
+20181012162028 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115E1C6FCB
+20181012182332 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115F5E2D97
+20181012182843 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115F623A23
+20181012201834 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211608810CB
+20181012223139 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21161EAF243
+20181013114842 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2116A336C63
+20181013221122 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21170A23417
+20181013221710 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21170A81107
+20181014032132 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21173C1D793
+20181014035731 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117416EF17
+20181014044029 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211747D7B4B
+20181014092738 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117764D6CF
+20181014125735 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21179863787
+20181014151837 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117AE70AF7
+20181014175821 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117C7CCCA7
+20181014225732 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117F8262DB
+20181014233346 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117FD8EA63
+20181015001106 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211803251C3
+20181015101051 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21185F9BDF3
+20181016055751 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211914B6C57
+20181016115955 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA20E92F77
+20181017081453 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA2E7C1F6B
+20181017142420 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA32237C3F
+20181017185818 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA353F763B
+20181017191239 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA355F350B
+20181018142458 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA4281917F
+20181018172424 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA44764C13
+20181019021923 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA4A5411D3
+20181019034359 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA4B386FC3
+20181019143855 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA5262DD0F
+20181019175117 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA547B23C3
+20181019180938 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA54A6C53B
+20181019200034 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA55D16287
+20181020003801 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA58CB384B
+20181020112657 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA5F85360B
+20181020201319 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA652B1403
+20181020203144 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA6552017F
+20181021021352 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA68F8AE73
+20181021071146 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA6C1C6B53
+20181021104137 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA6E492B5B
+20181021162701 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA71E3AEBB
+20181021164042 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA71FF6D23
+20181022114359 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA7D41FB5F
+20181023003127 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA852BE5A7
+20181023054524 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA88559E07
+20181023122409 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8C5B7A9F
+20181023161120 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8EA11AB7
+20181023174619 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8F91F893
+20181023175924 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8FAACDB7
diff --git a/moduli.0 b/moduli.0
index 59767da38315..a8109d7d7a6c 100644
--- a/moduli.0
+++ b/moduli.0
@@ -1,74 +1,74 @@
MODULI(5) File Formats Manual MODULI(5)
NAME
moduli M-bM-^@M-^S Diffie-Hellman moduli
DESCRIPTION
The /etc/moduli file contains prime numbers and generators for use by
sshd(8) in the Diffie-Hellman Group Exchange key exchange method.
New moduli may be generated with ssh-keygen(1) using a two-step process.
An initial candidate generation pass, using ssh-keygen -G, calculates
numbers that are likely to be useful. A second primality testing pass,
using ssh-keygen -T, provides a high degree of assurance that the numbers
are prime and are safe for use in Diffie-Hellman operations by sshd(8).
This moduli format is used as the output from each pass.
The file consists of newline-separated records, one per modulus,
containing seven space-separated fields. These fields are as follows:
timestamp The time that the modulus was last processed as
YYYYMMDDHHMMSS.
type Decimal number specifying the internal structure of
the prime modulus. Supported types are:
0 Unknown, not tested.
2 "Safe" prime; (p-1)/2 is also prime.
4 Sophie Germain; 2p+1 is also prime.
Moduli candidates initially produced by ssh-keygen(1)
are Sophie Germain primes (type 4). Further primality
testing with ssh-keygen(1) produces safe prime moduli
(type 2) that are ready for use in sshd(8). Other
types are not used by OpenSSH.
tests Decimal number indicating the type of primality tests
that the number has been subjected to represented as a
bitmask of the following values:
0x00 Not tested.
0x01 Composite number M-bM-^@M-^S not prime.
0x02 Sieve of Eratosthenes.
0x04 Probabilistic Miller-Rabin primality tests.
The ssh-keygen(1) moduli candidate generation uses the
Sieve of Eratosthenes (flag 0x02). Subsequent
ssh-keygen(1) primality tests are Miller-Rabin tests
(flag 0x04).
trials Decimal number indicating the number of primality
trials that have been performed on the modulus.
size Decimal number indicating the size of the prime in
bits.
generator The recommended generator for use with this modulus
(hexadecimal).
modulus The modulus itself in hexadecimal.
When performing Diffie-Hellman Group Exchange, sshd(8) first estimates
the size of the modulus required to produce enough Diffie-Hellman output
to sufficiently key the selected symmetric cipher. sshd(8) then randomly
selects a modulus from /etc/moduli that best meets the size requirement.
SEE ALSO
ssh-keygen(1), sshd(8)
STANDARDS
M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for
the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006,
2006.
-OpenBSD 6.4 September 26, 2012 OpenBSD 6.4
+OpenBSD 6.5 September 26, 2012 OpenBSD 6.5
diff --git a/moduli.c b/moduli.c
index 233cba8e881a..7120415fd8f8 100644
--- a/moduli.c
+++ b/moduli.c
@@ -1,808 +1,815 @@
-/* $OpenBSD: moduli.c,v 1.32 2017/12/08 03:45:52 deraadt Exp $ */
+/* $OpenBSD: moduli.c,v 1.34 2019/01/23 09:49:00 dtucker Exp $ */
/*
* Copyright 1994 Phil Karn <karn@qualcomm.com>
* Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
* Copyright 2000 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Two-step process to generate safe primes for DHGEX
*
* Sieve candidates for "safe" primes,
* suitable for use as Diffie-Hellman moduli;
* that is, where q = (p-1)/2 is also prime.
*
* First step: generate candidate primes (memory intensive)
* Second step: test primes' safety (processor intensive)
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <unistd.h>
#include <limits.h>
#include "xmalloc.h"
#include "dh.h"
#include "log.h"
#include "misc.h"
#include "openbsd-compat/openssl-compat.h"
/*
* File output defines
*/
/* need line long enough for largest moduli plus headers */
#define QLINESIZE (100+8192)
/*
* Size: decimal.
* Specifies the number of the most significant bit (0 to M).
* WARNING: internally, usually 1 to N.
*/
#define QSIZE_MINIMUM (511)
/*
* Prime sieving defines
*/
/* Constant: assuming 8 bit bytes and 32 bit words */
#define SHIFT_BIT (3)
#define SHIFT_BYTE (2)
#define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE)
#define SHIFT_MEGABYTE (20)
#define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE)
/*
* Using virtual memory can cause thrashing. This should be the largest
* number that is supported without a large amount of disk activity --
* that would increase the run time from hours to days or weeks!
*/
#define LARGE_MINIMUM (8UL) /* megabytes */
/*
* Do not increase this number beyond the unsigned integer bit size.
* Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits).
*/
#define LARGE_MAXIMUM (127UL) /* megabytes */
/*
* Constant: when used with 32-bit integers, the largest sieve prime
* has to be less than 2**32.
*/
#define SMALL_MAXIMUM (0xffffffffUL)
/* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */
#define TINY_NUMBER (1UL<<16)
/* Ensure enough bit space for testing 2*q. */
#define TEST_MAXIMUM (1UL<<16)
#define TEST_MINIMUM (QSIZE_MINIMUM + 1)
/* real TEST_MINIMUM (1UL << (SHIFT_WORD - TEST_POWER)) */
#define TEST_POWER (3) /* 2**n, n < SHIFT_WORD */
/* bit operations on 32-bit words */
#define BIT_CLEAR(a,n) ((a)[(n)>>SHIFT_WORD] &= ~(1L << ((n) & 31)))
#define BIT_SET(a,n) ((a)[(n)>>SHIFT_WORD] |= (1L << ((n) & 31)))
#define BIT_TEST(a,n) ((a)[(n)>>SHIFT_WORD] & (1L << ((n) & 31)))
/*
* Prime testing defines
*/
/* Minimum number of primality tests to perform */
#define TRIAL_MINIMUM (4)
/*
* Sieving data (XXX - move to struct)
*/
/* sieve 2**16 */
static u_int32_t *TinySieve, tinybits;
/* sieve 2**30 in 2**16 parts */
static u_int32_t *SmallSieve, smallbits, smallbase;
/* sieve relative to the initial value */
static u_int32_t *LargeSieve, largewords, largetries, largenumbers;
static u_int32_t largebits, largememory; /* megabytes */
static BIGNUM *largebase;
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
unsigned long);
/*
* print moduli out in consistent form,
*/
static int
qfileout(FILE * ofile, u_int32_t otype, u_int32_t otests, u_int32_t otries,
u_int32_t osize, u_int32_t ogenerator, BIGNUM * omodulus)
{
struct tm *gtm;
time_t time_now;
int res;
time(&time_now);
gtm = gmtime(&time_now);
res = fprintf(ofile, "%04d%02d%02d%02d%02d%02d %u %u %u %u %x ",
gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday,
gtm->tm_hour, gtm->tm_min, gtm->tm_sec,
otype, otests, otries, osize, ogenerator);
if (res < 0)
return (-1);
if (BN_print_fp(ofile, omodulus) < 1)
return (-1);
res = fprintf(ofile, "\n");
fflush(ofile);
return (res > 0 ? 0 : -1);
}
/*
** Sieve p's and q's with small factors
*/
static void
sieve_large(u_int32_t s)
{
u_int32_t r, u;
debug3("sieve_large %u", s);
largetries++;
/* r = largebase mod s */
r = BN_mod_word(largebase, s);
if (r == 0)
u = 0; /* s divides into largebase exactly */
else
u = s - r; /* largebase+u is first entry divisible by s */
if (u < largebits * 2) {
/*
* The sieve omits p's and q's divisible by 2, so ensure that
* largebase+u is odd. Then, step through the sieve in
* increments of 2*s
*/
if (u & 0x1)
u += s; /* Make largebase+u odd, and u even */
/* Mark all multiples of 2*s */
for (u /= 2; u < largebits; u += s)
BIT_SET(LargeSieve, u);
}
/* r = p mod s */
r = (2 * r + 1) % s;
if (r == 0)
u = 0; /* s divides p exactly */
else
u = s - r; /* p+u is first entry divisible by s */
if (u < largebits * 4) {
/*
* The sieve omits p's divisible by 4, so ensure that
* largebase+u is not. Then, step through the sieve in
* increments of 4*s
*/
while (u & 0x3) {
if (SMALL_MAXIMUM - u < s)
return;
u += s;
}
/* Mark all multiples of 4*s */
for (u /= 4; u < largebits; u += s)
BIT_SET(LargeSieve, u);
}
}
/*
* list candidates for Sophie-Germain primes (where q = (p-1)/2)
* to standard output.
* The list is checked against small known primes (less than 2**30).
*/
int
gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start)
{
BIGNUM *q;
u_int32_t j, r, s, t;
u_int32_t smallwords = TINY_NUMBER >> 6;
u_int32_t tinywords = TINY_NUMBER >> 6;
time_t time_start, time_stop;
u_int32_t i;
int ret = 0;
largememory = memory;
if (memory != 0 &&
(memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) {
error("Invalid memory amount (min %ld, max %ld)",
LARGE_MINIMUM, LARGE_MAXIMUM);
return (-1);
}
/*
* Set power to the length in bits of the prime to be generated.
* This is changed to 1 less than the desired safe prime moduli p.
*/
if (power > TEST_MAXIMUM) {
error("Too many bits: %u > %lu", power, TEST_MAXIMUM);
return (-1);
} else if (power < TEST_MINIMUM) {
error("Too few bits: %u < %u", power, TEST_MINIMUM);
return (-1);
}
power--; /* decrement before squaring */
/*
* The density of ordinary primes is on the order of 1/bits, so the
* density of safe primes should be about (1/bits)**2. Set test range
* to something well above bits**2 to be reasonably sure (but not
* guaranteed) of catching at least one safe prime.
*/
largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER));
/*
* Need idea of how much memory is available. We don't have to use all
* of it.
*/
if (largememory > LARGE_MAXIMUM) {
logit("Limited memory: %u MB; limit %lu MB",
largememory, LARGE_MAXIMUM);
largememory = LARGE_MAXIMUM;
}
if (largewords <= (largememory << SHIFT_MEGAWORD)) {
logit("Increased memory: %u MB; need %u bytes",
largememory, (largewords << SHIFT_BYTE));
largewords = (largememory << SHIFT_MEGAWORD);
} else if (largememory > 0) {
logit("Decreased memory: %u MB; want %u bytes",
largememory, (largewords << SHIFT_BYTE));
largewords = (largememory << SHIFT_MEGAWORD);
}
TinySieve = xcalloc(tinywords, sizeof(u_int32_t));
tinybits = tinywords << SHIFT_WORD;
SmallSieve = xcalloc(smallwords, sizeof(u_int32_t));
smallbits = smallwords << SHIFT_WORD;
/*
* dynamically determine available memory
*/
while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL)
largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */
largebits = largewords << SHIFT_WORD;
largenumbers = largebits * 2; /* even numbers excluded */
/* validation check: count the number of primes tried */
largetries = 0;
if ((q = BN_new()) == NULL)
fatal("BN_new failed");
/*
* Generate random starting point for subprime search, or use
* specified parameter.
*/
if ((largebase = BN_new()) == NULL)
fatal("BN_new failed");
if (start == NULL) {
if (BN_rand(largebase, power, 1, 1) == 0)
fatal("BN_rand failed");
} else {
if (BN_copy(largebase, start) == NULL)
fatal("BN_copy: failed");
}
/* ensure odd */
if (BN_set_bit(largebase, 0) == 0)
fatal("BN_set_bit: failed");
time(&time_start);
logit("%.24s Sieve next %u plus %u-bit", ctime(&time_start),
largenumbers, power);
debug2("start point: 0x%s", BN_bn2hex(largebase));
/*
* TinySieve
*/
for (i = 0; i < tinybits; i++) {
if (BIT_TEST(TinySieve, i))
continue; /* 2*i+3 is composite */
/* The next tiny prime */
t = 2 * i + 3;
/* Mark all multiples of t */
for (j = i + t; j < tinybits; j += t)
BIT_SET(TinySieve, j);
sieve_large(t);
}
/*
* Start the small block search at the next possible prime. To avoid
* fencepost errors, the last pass is skipped.
*/
for (smallbase = TINY_NUMBER + 3;
smallbase < (SMALL_MAXIMUM - TINY_NUMBER);
smallbase += TINY_NUMBER) {
for (i = 0; i < tinybits; i++) {
if (BIT_TEST(TinySieve, i))
continue; /* 2*i+3 is composite */
/* The next tiny prime */
t = 2 * i + 3;
r = smallbase % t;
if (r == 0) {
s = 0; /* t divides into smallbase exactly */
} else {
/* smallbase+s is first entry divisible by t */
s = t - r;
}
/*
* The sieve omits even numbers, so ensure that
* smallbase+s is odd. Then, step through the sieve
* in increments of 2*t
*/
if (s & 1)
s += t; /* Make smallbase+s odd, and s even */
/* Mark all multiples of 2*t */
for (s /= 2; s < smallbits; s += t)
BIT_SET(SmallSieve, s);
}
/*
* SmallSieve
*/
for (i = 0; i < smallbits; i++) {
if (BIT_TEST(SmallSieve, i))
continue; /* 2*i+smallbase is composite */
/* The next small prime */
sieve_large((2 * i) + smallbase);
}
memset(SmallSieve, 0, smallwords << SHIFT_BYTE);
}
time(&time_stop);
logit("%.24s Sieved with %u small primes in %lld seconds",
ctime(&time_stop), largetries, (long long)(time_stop - time_start));
for (j = r = 0; j < largebits; j++) {
if (BIT_TEST(LargeSieve, j))
continue; /* Definitely composite, skip */
debug2("test q = largebase+%u", 2 * j);
if (BN_set_word(q, 2 * j) == 0)
fatal("BN_set_word failed");
if (BN_add(q, q, largebase) == 0)
fatal("BN_add failed");
if (qfileout(out, MODULI_TYPE_SOPHIE_GERMAIN,
MODULI_TESTS_SIEVE, largetries,
(power - 1) /* MSB */, (0), q) == -1) {
ret = -1;
break;
}
r++; /* count q */
}
time(&time_stop);
free(LargeSieve);
free(SmallSieve);
free(TinySieve);
logit("%.24s Found %u candidates", ctime(&time_stop), r);
return (ret);
}
static void
write_checkpoint(char *cpfile, u_int32_t lineno)
{
FILE *fp;
char tmp[PATH_MAX];
int r;
r = snprintf(tmp, sizeof(tmp), "%s.XXXXXXXXXX", cpfile);
if (r == -1 || r >= PATH_MAX) {
logit("write_checkpoint: temp pathname too long");
return;
}
if ((r = mkstemp(tmp)) == -1) {
logit("mkstemp(%s): %s", tmp, strerror(errno));
return;
}
if ((fp = fdopen(r, "w")) == NULL) {
logit("write_checkpoint: fdopen: %s", strerror(errno));
unlink(tmp);
close(r);
return;
}
if (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0 && fclose(fp) == 0
&& rename(tmp, cpfile) == 0)
debug3("wrote checkpoint line %lu to '%s'",
(unsigned long)lineno, cpfile);
else
logit("failed to write to checkpoint file '%s': %s", cpfile,
strerror(errno));
}
static unsigned long
read_checkpoint(char *cpfile)
{
FILE *fp;
unsigned long lineno = 0;
if ((fp = fopen(cpfile, "r")) == NULL)
return 0;
if (fscanf(fp, "%lu\n", &lineno) < 1)
logit("Failed to load checkpoint from '%s'", cpfile);
else
logit("Loaded checkpoint from '%s' line %lu", cpfile, lineno);
fclose(fp);
return lineno;
}
static unsigned long
count_lines(FILE *f)
{
unsigned long count = 0;
char lp[QLINESIZE + 1];
if (fseek(f, 0, SEEK_SET) != 0) {
debug("input file is not seekable");
return ULONG_MAX;
}
while (fgets(lp, QLINESIZE + 1, f) != NULL)
count++;
rewind(f);
debug("input file has %lu lines", count);
return count;
}
static char *
fmt_time(time_t seconds)
{
int day, hr, min;
static char buf[128];
min = (seconds / 60) % 60;
hr = (seconds / 60 / 60) % 24;
day = seconds / 60 / 60 / 24;
if (day > 0)
snprintf(buf, sizeof buf, "%dd %d:%02d", day, hr, min);
else
snprintf(buf, sizeof buf, "%d:%02d", hr, min);
return buf;
}
static void
print_progress(unsigned long start_lineno, unsigned long current_lineno,
unsigned long end_lineno)
{
static time_t time_start, time_prev;
time_t time_now, elapsed;
unsigned long num_to_process, processed, remaining, percent, eta;
double time_per_line;
char *eta_str;
time_now = monotime();
if (time_start == 0) {
time_start = time_prev = time_now;
return;
}
/* print progress after 1m then once per 5m */
if (time_now - time_prev < 5 * 60)
return;
time_prev = time_now;
elapsed = time_now - time_start;
processed = current_lineno - start_lineno;
remaining = end_lineno - current_lineno;
num_to_process = end_lineno - start_lineno;
time_per_line = (double)elapsed / processed;
/* if we don't know how many we're processing just report count+time */
time(&time_now);
if (end_lineno == ULONG_MAX) {
logit("%.24s processed %lu in %s", ctime(&time_now),
processed, fmt_time(elapsed));
return;
}
percent = 100 * processed / num_to_process;
eta = time_per_line * remaining;
eta_str = xstrdup(fmt_time(eta));
logit("%.24s processed %lu of %lu (%lu%%) in %s, ETA %s",
ctime(&time_now), processed, num_to_process, percent,
fmt_time(elapsed), eta_str);
free(eta_str);
}
/*
* perform a Miller-Rabin primality test
* on the list of candidates
* (checking both q and p)
* The result is a list of so-call "safe" primes
*/
int
prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
char *checkpoint_file, unsigned long start_lineno, unsigned long num_lines)
{
BIGNUM *q, *p, *a;
BN_CTX *ctx;
char *cp, *lp;
u_int32_t count_in = 0, count_out = 0, count_possible = 0;
u_int32_t generator_known, in_tests, in_tries, in_type, in_size;
unsigned long last_processed = 0, end_lineno;
time_t time_start, time_stop;
- int res;
+ int res, is_prime;
if (trials < TRIAL_MINIMUM) {
error("Minimum primality trials is %d", TRIAL_MINIMUM);
return (-1);
}
if (num_lines == 0)
end_lineno = count_lines(in);
else
end_lineno = start_lineno + num_lines;
time(&time_start);
if ((p = BN_new()) == NULL)
fatal("BN_new failed");
if ((q = BN_new()) == NULL)
fatal("BN_new failed");
if ((ctx = BN_CTX_new()) == NULL)
fatal("BN_CTX_new failed");
debug2("%.24s Final %u Miller-Rabin trials (%x generator)",
ctime(&time_start), trials, generator_wanted);
if (checkpoint_file != NULL)
last_processed = read_checkpoint(checkpoint_file);
last_processed = start_lineno = MAXIMUM(last_processed, start_lineno);
if (end_lineno == ULONG_MAX)
debug("process from line %lu from pipe", last_processed);
else
debug("process from line %lu to line %lu", last_processed,
end_lineno);
res = 0;
lp = xmalloc(QLINESIZE + 1);
while (fgets(lp, QLINESIZE + 1, in) != NULL && count_in < end_lineno) {
count_in++;
if (count_in <= last_processed) {
debug3("skipping line %u, before checkpoint or "
"specified start line", count_in);
continue;
}
if (checkpoint_file != NULL)
write_checkpoint(checkpoint_file, count_in);
print_progress(start_lineno, count_in, end_lineno);
if (strlen(lp) < 14 || *lp == '!' || *lp == '#') {
debug2("%10u: comment or short line", count_in);
continue;
}
/* XXX - fragile parser */
/* time */
cp = &lp[14]; /* (skip) */
/* type */
in_type = strtoul(cp, &cp, 10);
/* tests */
in_tests = strtoul(cp, &cp, 10);
if (in_tests & MODULI_TESTS_COMPOSITE) {
debug2("%10u: known composite", count_in);
continue;
}
/* tries */
in_tries = strtoul(cp, &cp, 10);
/* size (most significant bit) */
in_size = strtoul(cp, &cp, 10);
/* generator (hex) */
generator_known = strtoul(cp, &cp, 16);
/* Skip white space */
cp += strspn(cp, " ");
/* modulus (hex) */
switch (in_type) {
case MODULI_TYPE_SOPHIE_GERMAIN:
debug2("%10u: (%u) Sophie-Germain", count_in, in_type);
a = q;
if (BN_hex2bn(&a, cp) == 0)
fatal("BN_hex2bn failed");
/* p = 2*q + 1 */
if (BN_lshift(p, q, 1) == 0)
fatal("BN_lshift failed");
if (BN_add_word(p, 1) == 0)
fatal("BN_add_word failed");
in_size += 1;
generator_known = 0;
break;
case MODULI_TYPE_UNSTRUCTURED:
case MODULI_TYPE_SAFE:
case MODULI_TYPE_SCHNORR:
case MODULI_TYPE_STRONG:
case MODULI_TYPE_UNKNOWN:
debug2("%10u: (%u)", count_in, in_type);
a = p;
if (BN_hex2bn(&a, cp) == 0)
fatal("BN_hex2bn failed");
/* q = (p-1) / 2 */
if (BN_rshift(q, p, 1) == 0)
fatal("BN_rshift failed");
break;
default:
debug2("Unknown prime type");
break;
}
/*
* due to earlier inconsistencies in interpretation, check
* the proposed bit size.
*/
if ((u_int32_t)BN_num_bits(p) != (in_size + 1)) {
debug2("%10u: bit size %u mismatch", count_in, in_size);
continue;
}
if (in_size < QSIZE_MINIMUM) {
debug2("%10u: bit size %u too short", count_in, in_size);
continue;
}
if (in_tests & MODULI_TESTS_MILLER_RABIN)
in_tries += trials;
else
in_tries = trials;
/*
* guess unknown generator
*/
if (generator_known == 0) {
if (BN_mod_word(p, 24) == 11)
generator_known = 2;
- else if (BN_mod_word(p, 12) == 5)
- generator_known = 3;
else {
u_int32_t r = BN_mod_word(p, 10);
if (r == 3 || r == 7)
generator_known = 5;
}
}
/*
* skip tests when desired generator doesn't match
*/
if (generator_wanted > 0 &&
generator_wanted != generator_known) {
debug2("%10u: generator %d != %d",
count_in, generator_known, generator_wanted);
continue;
}
/*
* Primes with no known generator are useless for DH, so
* skip those.
*/
if (generator_known == 0) {
debug2("%10u: no known generator", count_in);
continue;
}
count_possible++;
/*
* The (1/4)^N performance bound on Miller-Rabin is
* extremely pessimistic, so don't spend a lot of time
* really verifying that q is prime until after we know
* that p is also prime. A single pass will weed out the
* vast majority of composite q's.
*/
- if (BN_is_prime_ex(q, 1, ctx, NULL) <= 0) {
+ is_prime = BN_is_prime_ex(q, 1, ctx, NULL);
+ if (is_prime < 0)
+ fatal("BN_is_prime_ex failed");
+ if (is_prime == 0) {
debug("%10u: q failed first possible prime test",
count_in);
continue;
}
/*
* q is possibly prime, so go ahead and really make sure
* that p is prime. If it is, then we can go back and do
* the same for q. If p is composite, chances are that
* will show up on the first Rabin-Miller iteration so it
* doesn't hurt to specify a high iteration count.
*/
- if (!BN_is_prime_ex(p, trials, ctx, NULL)) {
+ is_prime = BN_is_prime_ex(p, trials, ctx, NULL);
+ if (is_prime < 0)
+ fatal("BN_is_prime_ex failed");
+ if (is_prime == 0) {
debug("%10u: p is not prime", count_in);
continue;
}
debug("%10u: p is almost certainly prime", count_in);
/* recheck q more rigorously */
- if (!BN_is_prime_ex(q, trials - 1, ctx, NULL)) {
+ is_prime = BN_is_prime_ex(q, trials - 1, ctx, NULL);
+ if (is_prime < 0)
+ fatal("BN_is_prime_ex failed");
+ if (is_prime == 0) {
debug("%10u: q is not prime", count_in);
continue;
}
debug("%10u: q is almost certainly prime", count_in);
if (qfileout(out, MODULI_TYPE_SAFE,
in_tests | MODULI_TESTS_MILLER_RABIN,
in_tries, in_size, generator_known, p)) {
res = -1;
break;
}
count_out++;
}
time(&time_stop);
free(lp);
BN_free(p);
BN_free(q);
BN_CTX_free(ctx);
if (checkpoint_file != NULL)
unlink(checkpoint_file);
logit("%.24s Found %u safe primes of %u candidates in %ld seconds",
ctime(&time_stop), count_out, count_possible,
(long) (time_stop - time_start));
return (res);
}
#endif /* WITH_OPENSSL */
diff --git a/monitor.c b/monitor.c
index 531b2993ab6b..60e529444478 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,1875 +1,1899 @@
-/* $OpenBSD: monitor.c,v 1.186 2018/07/20 03:46:34 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.197 2019/01/21 10:38:54 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include <signal.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
#endif
#ifdef WITH_OPENSSL
#include <openssl/dh.h>
#endif
#include "openbsd-compat/sys-tree.h"
#include "openbsd-compat/sys-queue.h"
#include "openbsd-compat/openssl-compat.h"
#include "atomicio.h"
#include "xmalloc.h"
#include "ssh.h"
#include "sshkey.h"
#include "sshbuf.h"
#include "hostfile.h"
#include "auth.h"
#include "cipher.h"
#include "kex.h"
#include "dh.h"
#include "auth-pam.h"
#include "packet.h"
#include "auth-options.h"
#include "sshpty.h"
#include "channels.h"
#include "session.h"
#include "sshlogin.h"
#include "canohost.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "monitor.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "monitor_fdpass.h"
#include "compat.h"
#include "ssh2.h"
#include "authfd.h"
#include "match.h"
#include "ssherr.h"
#ifdef GSSAPI
static Gssctxt *gsscontext = NULL;
#endif
/* Imports */
extern ServerOptions options;
extern u_int utmp_len;
extern u_char session_id[];
extern struct sshbuf *loginmsg;
extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
/* State exported from the child */
static struct sshbuf *child_state;
/* Functions on the monitor that answer unprivileged requests */
-int mm_answer_moduli(int, struct sshbuf *);
-int mm_answer_sign(int, struct sshbuf *);
-int mm_answer_pwnamallow(int, struct sshbuf *);
-int mm_answer_auth2_read_banner(int, struct sshbuf *);
-int mm_answer_authserv(int, struct sshbuf *);
-int mm_answer_authpassword(int, struct sshbuf *);
-int mm_answer_bsdauthquery(int, struct sshbuf *);
-int mm_answer_bsdauthrespond(int, struct sshbuf *);
-int mm_answer_keyallowed(int, struct sshbuf *);
-int mm_answer_keyverify(int, struct sshbuf *);
-int mm_answer_pty(int, struct sshbuf *);
-int mm_answer_pty_cleanup(int, struct sshbuf *);
-int mm_answer_term(int, struct sshbuf *);
-int mm_answer_rsa_keyallowed(int, struct sshbuf *);
-int mm_answer_rsa_challenge(int, struct sshbuf *);
-int mm_answer_rsa_response(int, struct sshbuf *);
-int mm_answer_sesskey(int, struct sshbuf *);
-int mm_answer_sessid(int, struct sshbuf *);
+int mm_answer_moduli(struct ssh *, int, struct sshbuf *);
+int mm_answer_sign(struct ssh *, int, struct sshbuf *);
+int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
+int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
+int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
+int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
+int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
+int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
+int mm_answer_skeyquery(struct ssh *, int, struct sshbuf *);
+int mm_answer_skeyrespond(struct ssh *, int, struct sshbuf *);
+int mm_answer_keyallowed(struct ssh *, int, struct sshbuf *);
+int mm_answer_keyverify(struct ssh *, int, struct sshbuf *);
+int mm_answer_pty(struct ssh *, int, struct sshbuf *);
+int mm_answer_pty_cleanup(struct ssh *, int, struct sshbuf *);
+int mm_answer_term(struct ssh *, int, struct sshbuf *);
+int mm_answer_rsa_keyallowed(struct ssh *, int, struct sshbuf *);
+int mm_answer_rsa_challenge(struct ssh *, int, struct sshbuf *);
+int mm_answer_rsa_response(struct ssh *, int, struct sshbuf *);
+int mm_answer_sesskey(struct ssh *, int, struct sshbuf *);
+int mm_answer_sessid(struct ssh *, int, struct sshbuf *);
#ifdef USE_PAM
-int mm_answer_pam_start(int, struct sshbuf *);
-int mm_answer_pam_account(int, struct sshbuf *);
-int mm_answer_pam_init_ctx(int, struct sshbuf *);
-int mm_answer_pam_query(int, struct sshbuf *);
-int mm_answer_pam_respond(int, struct sshbuf *);
-int mm_answer_pam_free_ctx(int, struct sshbuf *);
+int mm_answer_pam_start(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_account(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_init_ctx(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_query(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_respond(struct ssh *, int, struct sshbuf *);
+int mm_answer_pam_free_ctx(struct ssh *, int, struct sshbuf *);
#endif
#ifdef GSSAPI
-int mm_answer_gss_setup_ctx(int, struct sshbuf *);
-int mm_answer_gss_accept_ctx(int, struct sshbuf *);
-int mm_answer_gss_userok(int, struct sshbuf *);
-int mm_answer_gss_checkmic(int, struct sshbuf *);
+int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *);
+int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *);
+int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *);
+int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *);
#endif
#ifdef SSH_AUDIT_EVENTS
-int mm_answer_audit_event(int, struct sshbuf *);
-int mm_answer_audit_command(int, struct sshbuf *);
+int mm_answer_audit_event(struct ssh *, int, struct sshbuf *);
+int mm_answer_audit_command(struct ssh *, int, struct sshbuf *);
#endif
-static int monitor_read_log(struct monitor *);
-
static Authctxt *authctxt;
/* local state for key verify */
static u_char *key_blob = NULL;
static size_t key_bloblen = 0;
static int key_blobtype = MM_NOKEY;
static struct sshauthopt *key_opts = NULL;
static char *hostbased_cuser = NULL;
static char *hostbased_chost = NULL;
static char *auth_method = "unknown";
static char *auth_submethod = NULL;
static u_int session_id2_len = 0;
static u_char *session_id2 = NULL;
static pid_t monitor_child_pid;
struct mon_table {
enum monitor_reqtype type;
int flags;
- int (*f)(int, struct sshbuf *);
+ int (*f)(struct ssh *, int, struct sshbuf *);
};
#define MON_ISAUTH 0x0004 /* Required for Authentication */
#define MON_AUTHDECIDE 0x0008 /* Decides Authentication */
#define MON_ONCE 0x0010 /* Disable after calling */
#define MON_ALOG 0x0020 /* Log auth attempt without authenticating */
#define MON_AUTH (MON_ISAUTH|MON_AUTHDECIDE)
#define MON_PERMIT 0x1000 /* Request is permitted */
+static int monitor_read(struct ssh *, struct monitor *, struct mon_table *,
+ struct mon_table **);
+static int monitor_read_log(struct monitor *);
+
struct mon_table mon_dispatch_proto20[] = {
#ifdef WITH_OPENSSL
{MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
#endif
{MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
{MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
#ifdef USE_PAM
{MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
{MONITOR_REQ_PAM_ACCOUNT, 0, mm_answer_pam_account},
{MONITOR_REQ_PAM_INIT_CTX, MON_ONCE, mm_answer_pam_init_ctx},
{MONITOR_REQ_PAM_QUERY, 0, mm_answer_pam_query},
{MONITOR_REQ_PAM_RESPOND, MON_ONCE, mm_answer_pam_respond},
{MONITOR_REQ_PAM_FREE_CTX, MON_ONCE|MON_AUTHDECIDE, mm_answer_pam_free_ctx},
#endif
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
#endif
#ifdef BSD_AUTH
{MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
{MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH, mm_answer_bsdauthrespond},
#endif
{MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
{MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
#ifdef GSSAPI
{MONITOR_REQ_GSSSETUP, MON_ISAUTH, mm_answer_gss_setup_ctx},
{MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
{MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
{MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
#endif
{0, 0, NULL}
};
struct mon_table mon_dispatch_postauth20[] = {
#ifdef WITH_OPENSSL
{MONITOR_REQ_MODULI, 0, mm_answer_moduli},
#endif
{MONITOR_REQ_SIGN, 0, mm_answer_sign},
{MONITOR_REQ_PTY, 0, mm_answer_pty},
{MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
{MONITOR_REQ_TERM, 0, mm_answer_term},
#ifdef SSH_AUDIT_EVENTS
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
#endif
{0, 0, NULL}
};
struct mon_table *mon_dispatch;
/* Specifies if a certain message is allowed at the moment */
static void
monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
{
while (ent->f != NULL) {
if (ent->type == type) {
ent->flags &= ~MON_PERMIT;
ent->flags |= permit ? MON_PERMIT : 0;
return;
}
ent++;
}
}
static void
monitor_permit_authentications(int permit)
{
struct mon_table *ent = mon_dispatch;
while (ent->f != NULL) {
if (ent->flags & MON_AUTH) {
ent->flags &= ~MON_PERMIT;
ent->flags |= permit ? MON_PERMIT : 0;
}
ent++;
}
}
void
-monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
+monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
{
- struct ssh *ssh = active_state; /* XXX */
struct mon_table *ent;
int authenticated = 0, partial = 0;
debug3("preauth child monitor started");
if (pmonitor->m_recvfd >= 0)
close(pmonitor->m_recvfd);
if (pmonitor->m_log_sendfd >= 0)
close(pmonitor->m_log_sendfd);
pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
- authctxt = _authctxt;
+ authctxt = (Authctxt *)ssh->authctxt;
memset(authctxt, 0, sizeof(*authctxt));
ssh->authctxt = authctxt;
authctxt->loginmsg = loginmsg;
mon_dispatch = mon_dispatch_proto20;
/* Permit requests for moduli and signatures */
monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
/* The first few requests do not require asynchronous access */
while (!authenticated) {
partial = 0;
auth_method = "unknown";
auth_submethod = NULL;
auth2_authctxt_reset_info(authctxt);
- authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+ authenticated = (monitor_read(ssh, pmonitor,
+ mon_dispatch, &ent) == 1);
/* Special handling for multiple required authentications */
if (options.num_auth_methods != 0) {
if (authenticated &&
!auth2_update_methods_lists(authctxt,
auth_method, auth_submethod)) {
debug3("%s: method %s: partial", __func__,
auth_method);
authenticated = 0;
partial = 1;
}
}
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
fatal("%s: unexpected authentication from %d",
__func__, ent->type);
if (authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(ssh, auth_method))
authenticated = 0;
#ifdef USE_PAM
/* PAM needs to perform account checks after auth */
if (options.use_pam && authenticated) {
struct sshbuf *m;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed",
__func__);
mm_request_receive_expect(pmonitor->m_sendfd,
MONITOR_REQ_PAM_ACCOUNT, m);
authenticated = mm_answer_pam_account(
- pmonitor->m_sendfd, m);
+ ssh, pmonitor->m_sendfd, m);
sshbuf_free(m);
}
#endif
}
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
- auth_log(authctxt, authenticated, partial,
+ auth_log(ssh, authenticated, partial,
auth_method, auth_submethod);
if (!partial && !authenticated)
authctxt->failures++;
if (authenticated || partial) {
auth2_update_session_info(authctxt,
auth_method, auth_submethod);
}
}
}
if (!authctxt->valid)
fatal("%s: authenticated invalid user", __func__);
if (strcmp(auth_method, "unknown") == 0)
fatal("%s: authentication method name unknown", __func__);
debug("%s: %s has been authenticated by privileged process",
__func__, authctxt->user);
ssh->authctxt = NULL;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
- mm_get_keystate(pmonitor);
+ mm_get_keystate(ssh, pmonitor);
/* Drain any buffered messages from the child */
while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
;
if (pmonitor->m_recvfd >= 0)
close(pmonitor->m_recvfd);
if (pmonitor->m_log_sendfd >= 0)
close(pmonitor->m_log_sendfd);
pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
}
static void
monitor_set_child_handler(pid_t pid)
{
monitor_child_pid = pid;
}
static void
monitor_child_handler(int sig)
{
kill(monitor_child_pid, sig);
}
void
-monitor_child_postauth(struct monitor *pmonitor)
+monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor)
{
close(pmonitor->m_recvfd);
pmonitor->m_recvfd = -1;
monitor_set_child_handler(pmonitor->m_pid);
signal(SIGHUP, &monitor_child_handler);
signal(SIGTERM, &monitor_child_handler);
signal(SIGINT, &monitor_child_handler);
#ifdef SIGXFSZ
signal(SIGXFSZ, SIG_IGN);
#endif
mon_dispatch = mon_dispatch_postauth20;
/* Permit requests for moduli and signatures */
monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
if (auth_opts->permit_pty_flag) {
monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
}
for (;;)
- monitor_read(pmonitor, mon_dispatch, NULL);
+ monitor_read(ssh, pmonitor, mon_dispatch, NULL);
}
static int
monitor_read_log(struct monitor *pmonitor)
{
struct sshbuf *logmsg;
u_int len, level;
char *msg;
u_char *p;
int r;
if ((logmsg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
/* Read length */
if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0)
fatal("%s: reserve: %s", __func__, ssh_err(r));
if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) {
if (errno == EPIPE) {
sshbuf_free(logmsg);
debug("%s: child log fd closed", __func__);
close(pmonitor->m_log_recvfd);
pmonitor->m_log_recvfd = -1;
return -1;
}
fatal("%s: log fd read: %s", __func__, strerror(errno));
}
if ((r = sshbuf_get_u32(logmsg, &len)) != 0)
fatal("%s: get len: %s", __func__, ssh_err(r));
if (len <= 4 || len > 8192)
fatal("%s: invalid log message length %u", __func__, len);
/* Read severity, message */
sshbuf_reset(logmsg);
if ((r = sshbuf_reserve(logmsg, len, &p)) != 0)
fatal("%s: reserve: %s", __func__, ssh_err(r));
if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len)
fatal("%s: log fd read: %s", __func__, strerror(errno));
if ((r = sshbuf_get_u32(logmsg, &level)) != 0 ||
(r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
/* Log it */
if (log_level_name(level) == NULL)
fatal("%s: invalid log level %u (corrupted message?)",
__func__, level);
do_log2(level, "%s [preauth]", msg);
sshbuf_free(logmsg);
free(msg);
return 0;
}
-int
-monitor_read(struct monitor *pmonitor, struct mon_table *ent,
+static int
+monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
struct mon_table **pent)
{
struct sshbuf *m;
int r, ret;
u_char type;
struct pollfd pfd[2];
for (;;) {
memset(&pfd, 0, sizeof(pfd));
pfd[0].fd = pmonitor->m_sendfd;
pfd[0].events = POLLIN;
pfd[1].fd = pmonitor->m_log_recvfd;
pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN;
if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
fatal("%s: poll: %s", __func__, strerror(errno));
}
if (pfd[1].revents) {
/*
* Drain all log messages before processing next
* monitor request.
*/
monitor_read_log(pmonitor);
continue;
}
if (pfd[0].revents)
break; /* Continues below */
}
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
mm_request_receive(pmonitor->m_sendfd, m);
if ((r = sshbuf_get_u8(m, &type)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
debug3("%s: checking request %d", __func__, type);
while (ent->f != NULL) {
if (ent->type == type)
break;
ent++;
}
if (ent->f != NULL) {
if (!(ent->flags & MON_PERMIT))
fatal("%s: unpermitted request %d", __func__,
type);
- ret = (*ent->f)(pmonitor->m_sendfd, m);
+ ret = (*ent->f)(ssh, pmonitor->m_sendfd, m);
sshbuf_free(m);
/* The child may use this request only once, disable it */
if (ent->flags & MON_ONCE) {
debug2("%s: %d used once, disabling now", __func__,
type);
ent->flags &= ~MON_PERMIT;
}
if (pent != NULL)
*pent = ent;
return ret;
}
fatal("%s: unsupported request: %d", __func__, type);
/* NOTREACHED */
return (-1);
}
/* allowed key state */
static int
monitor_allowed_key(u_char *blob, u_int bloblen)
{
/* make sure key is allowed */
if (key_blob == NULL || key_bloblen != bloblen ||
timingsafe_bcmp(key_blob, blob, key_bloblen))
return (0);
return (1);
}
static void
monitor_reset_key_state(void)
{
/* reset state */
free(key_blob);
free(hostbased_cuser);
free(hostbased_chost);
sshauthopt_free(key_opts);
key_blob = NULL;
key_bloblen = 0;
key_blobtype = MM_NOKEY;
key_opts = NULL;
hostbased_cuser = NULL;
hostbased_chost = NULL;
}
#ifdef WITH_OPENSSL
int
-mm_answer_moduli(int sock, struct sshbuf *m)
+mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
{
DH *dh;
const BIGNUM *dh_p, *dh_g;
int r;
u_int min, want, max;
if ((r = sshbuf_get_u32(m, &min)) != 0 ||
(r = sshbuf_get_u32(m, &want)) != 0 ||
(r = sshbuf_get_u32(m, &max)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: got parameters: %d %d %d",
__func__, min, want, max);
/* We need to check here, too, in case the child got corrupted */
if (max < min || want < min || max < want)
fatal("%s: bad parameters: %d %d %d",
__func__, min, want, max);
sshbuf_reset(m);
dh = choose_dh(min, want, max);
if (dh == NULL) {
if ((r = sshbuf_put_u8(m, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
return (0);
} else {
/* Send first bignum */
DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
if ((r = sshbuf_put_u8(m, 1)) != 0 ||
(r = sshbuf_put_bignum2(m, dh_p)) != 0 ||
(r = sshbuf_put_bignum2(m, dh_g)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
DH_free(dh);
}
mm_request_send(sock, MONITOR_ANS_MODULI, m);
return (0);
}
#endif
int
-mm_answer_sign(int sock, struct sshbuf *m)
+mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
{
- struct ssh *ssh = active_state; /* XXX */
extern int auth_sock; /* XXX move to state struct? */
struct sshkey *key;
struct sshbuf *sigbuf = NULL;
u_char *p = NULL, *signature = NULL;
char *alg = NULL;
size_t datlen, siglen, alglen;
int r, is_proof = 0;
u_int keyid, compat;
const char proof_req[] = "hostkeys-prove-00@openssh.com";
debug3("%s", __func__);
if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
(r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
(r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 ||
(r = sshbuf_get_u32(m, &compat)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (keyid > INT_MAX)
fatal("%s: invalid key ID", __func__);
/*
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
* SHA384 (48 bytes) and SHA512 (64 bytes).
*
* Otherwise, verify the signature request is for a hostkey
* proof.
*
* XXX perform similar check for KEX signature requests too?
* it's not trivial, since what is signed is the hash, rather
* than the full kex structure...
*/
if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) {
/*
* Construct expected hostkey proof and compare it to what
* the client sent us.
*/
if (session_id2_len == 0) /* hostkeys is never first */
fatal("%s: bad data length: %zu", __func__, datlen);
if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL)
fatal("%s: no hostkey for index %d", __func__, keyid);
if ((sigbuf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 ||
(r = sshbuf_put_string(sigbuf, session_id2,
session_id2_len)) != 0 ||
(r = sshkey_puts(key, sigbuf)) != 0)
fatal("%s: couldn't prepare private key "
"proof buffer: %s", __func__, ssh_err(r));
if (datlen != sshbuf_len(sigbuf) ||
memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0)
fatal("%s: bad data length: %zu, hostkey proof len %zu",
__func__, datlen, sshbuf_len(sigbuf));
sshbuf_free(sigbuf);
is_proof = 1;
}
/* save session id, it will be passed on the first call */
if (session_id2_len == 0) {
session_id2_len = datlen;
session_id2 = xmalloc(session_id2_len);
memcpy(session_id2, p, session_id2_len);
}
if ((key = get_hostkey_by_index(keyid)) != NULL) {
if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
compat)) != 0)
fatal("%s: sshkey_sign failed: %s",
__func__, ssh_err(r));
} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
auth_sock > 0) {
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
p, datlen, alg, compat)) != 0) {
fatal("%s: ssh_agent_sign failed: %s",
__func__, ssh_err(r));
}
} else
fatal("%s: no hostkey from index %d", __func__, keyid);
debug3("%s: %s signature %p(%zu)", __func__,
is_proof ? "KEX" : "hostkey proof", signature, siglen);
sshbuf_reset(m);
if ((r = sshbuf_put_string(m, signature, siglen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(alg);
free(p);
free(signature);
mm_request_send(sock, MONITOR_ANS_SIGN, m);
/* Turn on permissions for getpwnam */
monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
return (0);
}
/* Retrieves the password entry and also checks if the user is permitted */
int
-mm_answer_pwnamallow(int sock, struct sshbuf *m)
+mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
{
- struct ssh *ssh = active_state; /* XXX */
char *username;
struct passwd *pwent;
int r, allowed = 0;
u_int i;
debug3("%s", __func__);
if (authctxt->attempt++ != 0)
fatal("%s: multiple attempts for getpwnam", __func__);
if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- pwent = getpwnamallow(username);
+ pwent = getpwnamallow(ssh, username);
authctxt->user = xstrdup(username);
setproctitle("%s [priv]", pwent ? username : "unknown");
free(username);
sshbuf_reset(m);
if (pwent == NULL) {
if ((r = sshbuf_put_u8(m, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
authctxt->pw = fakepw();
goto out;
}
allowed = 1;
authctxt->pw = pwent;
authctxt->valid = 1;
/* XXX don't sent pwent to unpriv; send fake class/dir/shell too */
if ((r = sshbuf_put_u8(m, 1)) != 0 ||
(r = sshbuf_put_string(m, pwent, sizeof(*pwent))) != 0 ||
(r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
(r = sshbuf_put_cstring(m, "*")) != 0 ||
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
(r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 ||
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
(r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 ||
#endif
(r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 ||
(r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
out:
ssh_packet_set_log_preamble(ssh, "%suser %s",
authctxt->valid ? "authenticating" : "invalid ", authctxt->user);
if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#define M_CP_STROPT(x) do { \
if (options.x != NULL) { \
if ((r = sshbuf_put_cstring(m, options.x)) != 0) \
fatal("%s: buffer error: %s", \
__func__, ssh_err(r)); \
} \
} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
for (i = 0; i < options.nx; i++) { \
if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \
fatal("%s: buffer error: %s", \
__func__, ssh_err(r)); \
} \
} while (0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
/* Create valid auth method lists */
if (auth2_setup_methods_lists(authctxt) != 0) {
/*
* The monitor will continue long enough to let the child
* run to it's packet_disconnect(), but it must not allow any
* authentication to succeed.
*/
debug("%s: no valid authentication method lists", __func__);
}
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
/* Allow service/style information on the auth context */
monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
#ifdef USE_PAM
if (options.use_pam)
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
#endif
return (0);
}
-int mm_answer_auth2_read_banner(int sock, struct sshbuf *m)
+int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *banner;
int r;
sshbuf_reset(m);
banner = auth2_read_banner();
if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
free(banner);
return (0);
}
int
-mm_answer_authserv(int sock, struct sshbuf *m)
+mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
{
int r;
monitor_permit_authentications(1);
if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: service=%s, style=%s",
__func__, authctxt->service, authctxt->style);
if (strlen(authctxt->style) == 0) {
free(authctxt->style);
authctxt->style = NULL;
}
return (0);
}
+/*
+ * Check that the key type appears in the supplied pattern list, ignoring
+ * mismatches in the signature algorithm. (Signature algorithm checks are
+ * performed in the unprivileged authentication code).
+ * Returns 1 on success, 0 otherwise.
+ */
+static int
+key_base_type_match(const char *method, const struct sshkey *key,
+ const char *list)
+{
+ char *s, *l, *ol = xstrdup(list);
+ int found = 0;
+
+ l = ol;
+ for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) {
+ if (sshkey_type_from_name(s) == key->type) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ error("%s key type %s is not in permitted list %s", method,
+ sshkey_ssh_name(key), list);
+ }
+
+ free(ol);
+ return found;
+}
+
int
-mm_answer_authpassword(int sock, struct sshbuf *m)
+mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
{
- struct ssh *ssh = active_state; /* XXX */
static int call_count;
char *passwd;
int r, authenticated;
size_t plen;
if (!options.password_authentication)
fatal("%s: password authentication not enabled", __func__);
if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* Only authenticate if the context is valid */
authenticated = options.password_authentication &&
auth_password(ssh, passwd);
explicit_bzero(passwd, plen);
free(passwd);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, authenticated)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifdef USE_PAM
if ((r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#endif
debug3("%s: sending result %d", __func__, authenticated);
mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
call_count++;
if (plen == 0 && call_count == 1)
auth_method = "none";
else
auth_method = "password";
/* Causes monitor loop to terminate if authenticated */
return (authenticated);
}
#ifdef BSD_AUTH
int
-mm_answer_bsdauthquery(int sock, struct sshbuf *m)
+mm_answer_bsdauthquery(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *name, *infotxt;
u_int numprompts, *echo_on, success;
char **prompts;
int r;
if (!options.kbd_interactive_authentication)
fatal("%s: kbd-int authentication not enabled", __func__);
success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
&prompts, &echo_on) < 0 ? 0 : 1;
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, success)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success) {
if ((r = sshbuf_put_cstring(m, prompts[0])) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
debug3("%s: sending challenge success: %u", __func__, success);
mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
if (success) {
free(name);
free(infotxt);
free(prompts);
free(echo_on);
}
return (0);
}
int
-mm_answer_bsdauthrespond(int sock, struct sshbuf *m)
+mm_answer_bsdauthrespond(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *response;
int r, authok;
if (!options.kbd_interactive_authentication)
fatal("%s: kbd-int authentication not enabled", __func__);
if (authctxt->as == NULL)
fatal("%s: no bsd auth session", __func__);
if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
authok = options.challenge_response_authentication &&
auth_userresponse(authctxt->as, response, 0);
authctxt->as = NULL;
debug3("%s: <%s> = <%d>", __func__, response, authok);
free(response);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, authok)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: sending authenticated: %d", __func__, authok);
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
auth_method = "keyboard-interactive";
auth_submethod = "bsdauth";
return (authok != 0);
}
#endif
#ifdef USE_PAM
int
-mm_answer_pam_start(int sock, struct sshbuf *m)
+mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m)
{
if (!options.use_pam)
fatal("UsePAM not set, but ended up in %s anyway", __func__);
- start_pam(authctxt);
+ start_pam(ssh);
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_ACCOUNT, 1);
if (options.kbd_interactive_authentication)
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1);
return (0);
}
int
-mm_answer_pam_account(int sock, struct sshbuf *m)
+mm_answer_pam_account(struct ssh *ssh, int sock, struct sshbuf *m)
{
u_int ret;
int r;
if (!options.use_pam)
fatal("%s: PAM not enabled", __func__);
ret = do_pam_account();
if ((r = sshbuf_put_u32(m, ret)) != 0 ||
(r = sshbuf_put_stringb(m, loginmsg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m);
return (ret);
}
static void *sshpam_ctxt, *sshpam_authok;
extern KbdintDevice sshpam_device;
int
-mm_answer_pam_init_ctx(int sock, struct sshbuf *m)
+mm_answer_pam_init_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
u_int ok = 0;
int r;
debug3("%s", __func__);
if (!options.kbd_interactive_authentication)
fatal("%s: kbd-int authentication not enabled", __func__);
if (sshpam_ctxt != NULL)
fatal("%s: already called", __func__);
sshpam_ctxt = (sshpam_device.init_ctx)(authctxt);
sshpam_authok = NULL;
sshbuf_reset(m);
if (sshpam_ctxt != NULL) {
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_FREE_CTX, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_QUERY, 1);
ok = 1;
}
if ((r = sshbuf_put_u32(m, ok)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m);
return (0);
}
int
-mm_answer_pam_query(int sock, struct sshbuf *m)
+mm_answer_pam_query(struct ssh *ssh, int sock, struct sshbuf *m)
{
char *name = NULL, *info = NULL, **prompts = NULL;
u_int i, num = 0, *echo_on = 0;
int r, ret;
debug3("%s", __func__);
sshpam_authok = NULL;
if (sshpam_ctxt == NULL)
fatal("%s: no context", __func__);
ret = (sshpam_device.query)(sshpam_ctxt, &name, &info,
&num, &prompts, &echo_on);
if (ret == 0 && num == 0)
sshpam_authok = sshpam_ctxt;
if (num > 1 || name == NULL || info == NULL)
fatal("sshpam_device.query failed");
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_RESPOND, 1);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, ret)) != 0 ||
(r = sshbuf_put_cstring(m, name)) != 0 ||
(r = sshbuf_put_cstring(m, info)) != 0 ||
(r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0 ||
(r = sshbuf_put_u32(m, num)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(name);
free(info);
for (i = 0; i < num; ++i) {
if ((r = sshbuf_put_cstring(m, prompts[i])) != 0 ||
(r = sshbuf_put_u32(m, echo_on[i])) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(prompts[i]);
}
free(prompts);
free(echo_on);
auth_method = "keyboard-interactive";
auth_submethod = "pam";
mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
return (0);
}
int
-mm_answer_pam_respond(int sock, struct sshbuf *m)
+mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m)
{
char **resp;
u_int i, num;
int r, ret;
debug3("%s", __func__);
if (sshpam_ctxt == NULL)
fatal("%s: no context", __func__);
sshpam_authok = NULL;
if ((r = sshbuf_get_u32(m, &num)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (num > 0) {
resp = xcalloc(num, sizeof(char *));
for (i = 0; i < num; ++i) {
if ((r = sshbuf_get_cstring(m, &(resp[i]), NULL)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
ret = (sshpam_device.respond)(sshpam_ctxt, num, resp);
for (i = 0; i < num; ++i)
free(resp[i]);
free(resp);
} else {
ret = (sshpam_device.respond)(sshpam_ctxt, num, NULL);
}
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, ret)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
auth_method = "keyboard-interactive";
auth_submethod = "pam";
if (ret == 0)
sshpam_authok = sshpam_ctxt;
return (0);
}
int
-mm_answer_pam_free_ctx(int sock, struct sshbuf *m)
+mm_answer_pam_free_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt;
debug3("%s", __func__);
if (sshpam_ctxt == NULL)
fatal("%s: no context", __func__);
(sshpam_device.free_ctx)(sshpam_ctxt);
sshpam_ctxt = sshpam_authok = NULL;
sshbuf_reset(m);
mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
/* Allow another attempt */
monitor_permit(mon_dispatch, MONITOR_REQ_PAM_INIT_CTX, 1);
auth_method = "keyboard-interactive";
auth_submethod = "pam";
return r;
}
#endif
int
-mm_answer_keyallowed(int sock, struct sshbuf *m)
+mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshkey *key = NULL;
char *cuser, *chost;
u_int pubkey_auth_attempt;
enum mm_keytype type = 0;
int r, allowed = 0;
struct sshauthopt *opts = NULL;
debug3("%s entering", __func__);
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
(r = sshkey_froms(m, &key)) != 0 ||
(r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: key_from_blob: %p", __func__, key);
if (key != NULL && authctxt->valid) {
/* These should not make it past the privsep child */
if (sshkey_type_plain(key->type) == KEY_RSA &&
(datafellows & SSH_BUG_RSASIGMD5) != 0)
fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);
switch (type) {
case MM_USERKEY:
auth_method = "publickey";
if (!options.pubkey_authentication)
break;
if (auth2_key_already_used(authctxt, key))
break;
- if (match_pattern_list(sshkey_ssh_name(key),
- options.pubkey_key_types, 0) != 1)
+ if (!key_base_type_match(auth_method, key,
+ options.pubkey_key_types))
break;
allowed = user_key_allowed(ssh, authctxt->pw, key,
pubkey_auth_attempt, &opts);
break;
case MM_HOSTKEY:
auth_method = "hostbased";
if (!options.hostbased_authentication)
break;
if (auth2_key_already_used(authctxt, key))
break;
- if (match_pattern_list(sshkey_ssh_name(key),
- options.hostbased_key_types, 0) != 1)
+ if (!key_base_type_match(auth_method, key,
+ options.hostbased_key_types))
break;
- allowed = hostbased_key_allowed(authctxt->pw,
+ allowed = hostbased_key_allowed(ssh, authctxt->pw,
cuser, chost, key);
auth2_record_info(authctxt,
"client user \"%.100s\", client host \"%.100s\"",
cuser, chost);
break;
default:
fatal("%s: unknown key type %d", __func__, type);
break;
}
}
debug3("%s: %s authentication%s: %s key is %s", __func__,
auth_method, pubkey_auth_attempt ? "" : " test",
(key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key),
allowed ? "allowed" : "not allowed");
auth2_record_key(authctxt, 0, key);
/* clear temporarily storage (used by verify) */
monitor_reset_key_state();
if (allowed) {
/* Save temporarily for comparison in verify */
if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
key_blobtype = type;
key_opts = opts;
hostbased_cuser = cuser;
hostbased_chost = chost;
} else {
/* Log failed attempt */
- auth_log(authctxt, 0, 0, auth_method, NULL);
+ auth_log(ssh, 0, 0, auth_method, NULL);
free(cuser);
free(chost);
}
sshkey_free(key);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, allowed)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0)
fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
if (!allowed)
sshauthopt_free(opts);
return (0);
}
static int
monitor_valid_userblob(u_char *data, u_int datalen)
{
struct sshbuf *b;
const u_char *p;
char *userstyle, *cp;
size_t len;
u_char type;
int r, fail = 0;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put(b, data, datalen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (datafellows & SSH_OLD_SESSIONID) {
p = sshbuf_ptr(b);
len = sshbuf_len(b);
if ((session_id2 == NULL) ||
(len < session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
if ((r = sshbuf_consume(b, session_id2_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else {
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
}
if ((r = sshbuf_get_u8(b, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
if (strcmp(userstyle, cp) != 0) {
logit("wrong user name passed to monitor: "
"expected %s != %.100s", userstyle, cp);
fail++;
}
free(userstyle);
free(cp);
if ((r = sshbuf_skip_string(b)) != 0 || /* service */
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp("publickey", cp) != 0)
fail++;
free(cp);
if ((r = sshbuf_get_u8(b, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (type == 0)
fail++;
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */
(r = sshbuf_skip_string(b)) != 0) /* pkblob */
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (sshbuf_len(b) != 0)
fail++;
sshbuf_free(b);
return (fail == 0);
}
static int
monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser,
char *chost)
{
struct sshbuf *b;
const u_char *p;
char *cp, *userstyle;
size_t len;
int r, fail = 0;
u_char type;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put(b, data, datalen)) != 0 ||
(r = sshbuf_get_string_direct(b, &p, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
if ((r = sshbuf_get_u8(b, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
if (strcmp(userstyle, cp) != 0) {
logit("wrong user name passed to monitor: "
"expected %s != %.100s", userstyle, cp);
fail++;
}
free(userstyle);
free(cp);
if ((r = sshbuf_skip_string(b)) != 0 || /* service */
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp(cp, "hostbased") != 0)
fail++;
free(cp);
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */
(r = sshbuf_skip_string(b)) != 0) /* pkblob */
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* verify client host, strip trailing dot if necessary */
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (((len = strlen(cp)) > 0) && cp[len - 1] == '.')
cp[len - 1] = '\0';
if (strcmp(cp, chost) != 0)
fail++;
free(cp);
/* verify client user */
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp(cp, cuser) != 0)
fail++;
free(cp);
if (sshbuf_len(b) != 0)
fail++;
sshbuf_free(b);
return (fail == 0);
}
int
-mm_answer_keyverify(int sock, struct sshbuf *m)
+mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshkey *key;
u_char *signature, *data, *blob;
char *sigalg;
size_t signaturelen, datalen, bloblen;
int r, ret, valid_data = 0, encoded_ret;
if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 ||
(r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 ||
(r = sshbuf_get_string(m, &data, &datalen)) != 0 ||
(r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
!monitor_allowed_key(blob, bloblen))
fatal("%s: bad key, not previously allowed", __func__);
/* Empty signature algorithm means NULL. */
if (*sigalg == '\0') {
free(sigalg);
sigalg = NULL;
}
/* XXX use sshkey_froms here; need to change key_blob, etc. */
if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0)
fatal("%s: bad public key blob: %s", __func__, ssh_err(r));
switch (key_blobtype) {
case MM_USERKEY:
valid_data = monitor_valid_userblob(data, datalen);
auth_method = "publickey";
break;
case MM_HOSTKEY:
valid_data = monitor_valid_hostbasedblob(data, datalen,
hostbased_cuser, hostbased_chost);
auth_method = "hostbased";
break;
default:
valid_data = 0;
break;
}
if (!valid_data)
fatal("%s: bad signature data blob", __func__);
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
- sigalg, active_state->compat);
+ sigalg, ssh->compat);
debug3("%s: %s %p signature %s", __func__, auth_method, key,
(ret == 0) ? "verified" : "unverified");
auth2_record_key(authctxt, ret == 0, key);
free(blob);
free(signature);
free(data);
free(sigalg);
if (key_blobtype == MM_USERKEY)
auth_activate_options(ssh, key_opts);
monitor_reset_key_state();
sshkey_free(key);
sshbuf_reset(m);
/* encode ret != 0 as positive integer, since we're sending u32 */
encoded_ret = (ret != 0);
if ((r = sshbuf_put_u32(m, encoded_ret)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
return ret == 0;
}
static void
-mm_record_login(Session *s, struct passwd *pw)
+mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw)
{
- struct ssh *ssh = active_state; /* XXX */
socklen_t fromlen;
struct sockaddr_storage from;
/*
* Get IP address of client. If the connection is not a socket, let
* the address be 0.0.0.0.
*/
memset(&from, 0, sizeof(from));
fromlen = sizeof(from);
- if (packet_connection_is_on_socket()) {
- if (getpeername(packet_get_connection_in(),
+ if (ssh_packet_connection_is_on_socket(ssh)) {
+ if (getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
cleanup_exit(255);
}
}
/* Record that there was a login on that tty from the remote host. */
record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns),
(struct sockaddr *)&from, fromlen);
}
static void
mm_session_close(Session *s)
{
debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
if (s->ttyfd != -1) {
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
session_pty_cleanup2(s);
}
session_unused(s->self);
}
int
-mm_answer_pty(int sock, struct sshbuf *m)
+mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
{
extern struct monitor *pmonitor;
Session *s;
int r, res, fd0;
debug3("%s entering", __func__);
sshbuf_reset(m);
s = session_new();
if (s == NULL)
goto error;
s->authctxt = authctxt;
s->pw = authctxt->pw;
s->pid = pmonitor->m_pid;
res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
if (res == 0)
goto error;
pty_setowner(authctxt->pw, s->tty);
if ((r = sshbuf_put_u32(m, 1)) != 0 ||
(r = sshbuf_put_cstring(m, s->tty)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* We need to trick ttyslot */
if (dup2(s->ttyfd, 0) == -1)
fatal("%s: dup2", __func__);
- mm_record_login(s, authctxt->pw);
+ mm_record_login(ssh, s, authctxt->pw);
/* Now we can close the file descriptor again */
close(0);
/* send messages generated by record_login */
if ((r = sshbuf_put_stringb(m, loginmsg)) != 0)
fatal("%s: put login message: %s", __func__, ssh_err(r));
sshbuf_reset(loginmsg);
mm_request_send(sock, MONITOR_ANS_PTY, m);
if (mm_send_fd(sock, s->ptyfd) == -1 ||
mm_send_fd(sock, s->ttyfd) == -1)
fatal("%s: send fds failed", __func__);
/* make sure nothing uses fd 0 */
if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
if (fd0 != 0)
error("%s: fd0 %d != 0", __func__, fd0);
/* slave is not needed */
close(s->ttyfd);
s->ttyfd = s->ptyfd;
/* no need to dup() because nobody closes ptyfd */
s->ptymaster = s->ptyfd;
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
return (0);
error:
if (s != NULL)
mm_session_close(s);
if ((r = sshbuf_put_u32(m, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_PTY, m);
return (0);
}
int
-mm_answer_pty_cleanup(int sock, struct sshbuf *m)
+mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m)
{
Session *s;
char *tty;
int r;
debug3("%s entering", __func__);
if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((s = session_by_tty(tty)) != NULL)
mm_session_close(s);
sshbuf_reset(m);
free(tty);
return (0);
}
int
-mm_answer_term(int sock, struct sshbuf *req)
+mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req)
{
- struct ssh *ssh = active_state; /* XXX */
extern struct monitor *pmonitor;
int res, status;
debug3("%s: tearing down sessions", __func__);
/* The child is terminating */
session_destroy_all(ssh, &mm_session_close);
#ifdef USE_PAM
if (options.use_pam)
sshpam_cleanup();
#endif
while (waitpid(pmonitor->m_pid, &status, 0) == -1)
if (errno != EINTR)
exit(1);
res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
/* Terminate process */
exit(res);
}
#ifdef SSH_AUDIT_EVENTS
/* Report that an audit event occurred */
int
-mm_answer_audit_event(int socket, struct sshbuf *m)
+mm_answer_audit_event(struct ssh *ssh, int socket, struct sshbuf *m)
{
u_int n;
ssh_audit_event_t event;
int r;
debug3("%s entering", __func__);
if ((r = sshbuf_get_u32(m, &n)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
event = (ssh_audit_event_t)n;
switch (event) {
case SSH_AUTH_FAIL_PUBKEY:
case SSH_AUTH_FAIL_HOSTBASED:
case SSH_AUTH_FAIL_GSSAPI:
case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
case SSH_CONNECTION_CLOSE:
case SSH_INVALID_USER:
- audit_event(event);
+ audit_event(ssh, event);
break;
default:
fatal("Audit event type %d not permitted", event);
}
return (0);
}
int
-mm_answer_audit_command(int socket, struct sshbuf *m)
+mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m)
{
char *cmd;
int r;
debug3("%s entering", __func__);
if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* sanity check command, if so how? */
audit_run_command(cmd);
free(cmd);
return (0);
}
#endif /* SSH_AUDIT_EVENTS */
void
-monitor_clear_keystate(struct monitor *pmonitor)
+monitor_clear_keystate(struct ssh *ssh, struct monitor *pmonitor)
{
- struct ssh *ssh = active_state; /* XXX */
-
ssh_clear_newkeys(ssh, MODE_IN);
ssh_clear_newkeys(ssh, MODE_OUT);
sshbuf_free(child_state);
child_state = NULL;
}
void
-monitor_apply_keystate(struct monitor *pmonitor)
+monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
{
- struct ssh *ssh = active_state; /* XXX */
struct kex *kex;
int r;
debug3("%s: packet_set_state", __func__);
if ((r = ssh_packet_set_state(ssh, child_state)) != 0)
fatal("%s: packet_set_state: %s", __func__, ssh_err(r));
sshbuf_free(child_state);
child_state = NULL;
if ((kex = ssh->kex) != NULL) {
/* XXX set callbacks */
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
- kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server;
- kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server;
- kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server;
+ kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif /* WITH_OPENSSL */
- kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
kex->sign = sshd_hostkey_sign;
}
}
/* This function requries careful sanity checking */
void
-mm_get_keystate(struct monitor *pmonitor)
+mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor)
{
debug3("%s: Waiting for new keys", __func__);
if ((child_state = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT,
child_state);
debug3("%s: GOT new keys", __func__);
}
/* XXX */
#define FD_CLOSEONEXEC(x) do { \
if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \
fatal("fcntl(%d, F_SETFD)", x); \
} while (0)
static void
monitor_openfds(struct monitor *mon, int do_logfds)
{
int pair[2];
#ifdef SO_ZEROIZE
int on = 1;
#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
fatal("%s: socketpair: %s", __func__, strerror(errno));
#ifdef SO_ZEROIZE
if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0)
error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno));
if (setsockopt(pair[1], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) < 0)
error("setsockopt SO_ZEROIZE(1): %.100s", strerror(errno));
#endif
FD_CLOSEONEXEC(pair[0]);
FD_CLOSEONEXEC(pair[1]);
mon->m_recvfd = pair[0];
mon->m_sendfd = pair[1];
if (do_logfds) {
if (pipe(pair) == -1)
fatal("%s: pipe: %s", __func__, strerror(errno));
FD_CLOSEONEXEC(pair[0]);
FD_CLOSEONEXEC(pair[1]);
mon->m_log_recvfd = pair[0];
mon->m_log_sendfd = pair[1];
} else
mon->m_log_recvfd = mon->m_log_sendfd = -1;
}
#define MM_MEMSIZE 65536
struct monitor *
monitor_init(void)
{
struct monitor *mon;
mon = xcalloc(1, sizeof(*mon));
monitor_openfds(mon, 1);
return mon;
}
void
monitor_reinit(struct monitor *mon)
{
monitor_openfds(mon, 0);
}
#ifdef GSSAPI
int
-mm_answer_gss_setup_ctx(int sock, struct sshbuf *m)
+mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
gss_OID_desc goid;
OM_uint32 major;
size_t len;
u_char *p;
int r;
if (!options.gss_authentication)
fatal("%s: GSSAPI authentication not enabled", __func__);
if ((r = sshbuf_get_string(m, &p, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
goid.elements = p;
goid.length = len;
major = ssh_gssapi_server_ctx(&gsscontext, &goid);
free(goid.elements);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, major)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
/* Now we have a context, enable the step */
monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 1);
return (0);
}
int
-mm_answer_gss_accept_ctx(int sock, struct sshbuf *m)
+mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
{
gss_buffer_desc in;
gss_buffer_desc out = GSS_C_EMPTY_BUFFER;
OM_uint32 major, minor;
OM_uint32 flags = 0; /* GSI needs this */
int r;
if (!options.gss_authentication)
fatal("%s: GSSAPI authentication not enabled", __func__);
if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
free(in.value);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, major)) != 0 ||
(r = sshbuf_put_string(m, out.value, out.length)) != 0 ||
(r = sshbuf_put_u32(m, flags)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
gss_release_buffer(&minor, &out);
if (major == GSS_S_COMPLETE) {
monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
}
return (0);
}
int
-mm_answer_gss_checkmic(int sock, struct sshbuf *m)
+mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m)
{
gss_buffer_desc gssbuf, mic;
OM_uint32 ret;
int r;
if (!options.gss_authentication)
fatal("%s: GSSAPI authentication not enabled", __func__);
if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 ||
(r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
free(gssbuf.value);
free(mic.value);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, ret)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
if (!GSS_ERROR(ret))
monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
return (0);
}
int
-mm_answer_gss_userok(int sock, struct sshbuf *m)
+mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
{
int r, authenticated;
const char *displayname;
if (!options.gss_authentication)
fatal("%s: GSSAPI authentication not enabled", __func__);
authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, authenticated)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: sending result %d", __func__, authenticated);
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
auth_method = "gssapi-with-mic";
if ((displayname = ssh_gssapi_displayname()) != NULL)
auth2_record_info(authctxt, "%s", displayname);
/* Monitor loop will terminate if authenticated */
return (authenticated);
}
#endif /* GSSAPI */
diff --git a/monitor.h b/monitor.h
index 16047299f882..683e5e07163e 100644
--- a/monitor.h
+++ b/monitor.h
@@ -1,92 +1,95 @@
-/* $OpenBSD: monitor.h,v 1.21 2018/07/09 21:53:45 markus Exp $ */
+/* $OpenBSD: monitor.h,v 1.23 2019/01/19 21:43:56 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MONITOR_H_
#define _MONITOR_H_
/* Please keep *_REQ_* values on even numbers and *_ANS_* on odd numbers */
enum monitor_reqtype {
MONITOR_REQ_MODULI = 0, MONITOR_ANS_MODULI = 1,
MONITOR_REQ_FREE = 2,
MONITOR_REQ_AUTHSERV = 4,
MONITOR_REQ_SIGN = 6, MONITOR_ANS_SIGN = 7,
MONITOR_REQ_PWNAM = 8, MONITOR_ANS_PWNAM = 9,
MONITOR_REQ_AUTH2_READ_BANNER = 10, MONITOR_ANS_AUTH2_READ_BANNER = 11,
MONITOR_REQ_AUTHPASSWORD = 12, MONITOR_ANS_AUTHPASSWORD = 13,
MONITOR_REQ_BSDAUTHQUERY = 14, MONITOR_ANS_BSDAUTHQUERY = 15,
MONITOR_REQ_BSDAUTHRESPOND = 16, MONITOR_ANS_BSDAUTHRESPOND = 17,
MONITOR_REQ_KEYALLOWED = 22, MONITOR_ANS_KEYALLOWED = 23,
MONITOR_REQ_KEYVERIFY = 24, MONITOR_ANS_KEYVERIFY = 25,
MONITOR_REQ_KEYEXPORT = 26,
MONITOR_REQ_PTY = 28, MONITOR_ANS_PTY = 29,
MONITOR_REQ_PTYCLEANUP = 30,
MONITOR_REQ_SESSKEY = 32, MONITOR_ANS_SESSKEY = 33,
MONITOR_REQ_SESSID = 34,
MONITOR_REQ_RSAKEYALLOWED = 36, MONITOR_ANS_RSAKEYALLOWED = 37,
MONITOR_REQ_RSACHALLENGE = 38, MONITOR_ANS_RSACHALLENGE = 39,
MONITOR_REQ_RSARESPONSE = 40, MONITOR_ANS_RSARESPONSE = 41,
MONITOR_REQ_GSSSETUP = 42, MONITOR_ANS_GSSSETUP = 43,
MONITOR_REQ_GSSSTEP = 44, MONITOR_ANS_GSSSTEP = 45,
MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
MONITOR_REQ_TERM = 50,
MONITOR_REQ_PAM_START = 100,
MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105,
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
};
+struct ssh;
+
struct monitor {
int m_recvfd;
int m_sendfd;
int m_log_recvfd;
int m_log_sendfd;
struct kex **m_pkex;
pid_t m_pid;
};
struct monitor *monitor_init(void);
void monitor_reinit(struct monitor *);
struct Authctxt;
-void monitor_child_preauth(struct Authctxt *, struct monitor *);
-void monitor_child_postauth(struct monitor *);
+void monitor_child_preauth(struct ssh *, struct monitor *);
+void monitor_child_postauth(struct ssh *, struct monitor *);
-struct mon_table;
-int monitor_read(struct monitor*, struct mon_table *, struct mon_table **);
+void monitor_clear_keystate(struct ssh *, struct monitor *);
+void monitor_apply_keystate(struct ssh *, struct monitor *);
/* Prototypes for request sending and receiving */
void mm_request_send(int, enum monitor_reqtype, struct sshbuf *);
void mm_request_receive(int, struct sshbuf *);
void mm_request_receive_expect(int, enum monitor_reqtype, struct sshbuf *);
+void mm_get_keystate(struct ssh *, struct monitor *);
#endif /* _MONITOR_H_ */
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 732fb3476bf0..186e8f0223f5 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,1006 +1,1000 @@
-/* $OpenBSD: monitor_wrap.c,v 1.107 2018/07/20 03:46:34 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.112 2019/01/21 09:54:11 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/uio.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef WITH_OPENSSL
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/evp.h>
#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#ifdef WITH_OPENSSL
#include "dh.h"
#endif
#include "sshbuf.h"
#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "packet.h"
#include "mac.h"
#include "log.h"
#include "auth-pam.h"
#include "monitor.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "misc.h"
#include "channels.h"
#include "session.h"
#include "servconf.h"
#include "ssherr.h"
/* Imports */
extern struct monitor *pmonitor;
extern struct sshbuf *loginmsg;
extern ServerOptions options;
void
mm_log_handler(LogLevel level, const char *msg, void *ctx)
{
struct sshbuf *log_msg;
struct monitor *mon = (struct monitor *)ctx;
int r;
size_t len;
if (mon->m_log_sendfd == -1)
fatal("%s: no log channel", __func__);
if ((log_msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
(r = sshbuf_put_u32(log_msg, level)) != 0 ||
(r = sshbuf_put_cstring(log_msg, msg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
fatal("%s: bad length %zu", __func__, len);
POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
if (atomicio(vwrite, mon->m_log_sendfd,
sshbuf_mutable_ptr(log_msg), len) != len)
fatal("%s: write: %s", __func__, strerror(errno));
sshbuf_free(log_msg);
}
int
mm_is_monitor(void)
{
/*
* m_pid is only set in the privileged part, and
* points to the unprivileged child.
*/
return (pmonitor && pmonitor->m_pid > 0);
}
void
mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
{
size_t mlen = sshbuf_len(m);
u_char buf[5];
debug3("%s entering: type %d", __func__, type);
if (mlen >= 0xffffffff)
fatal("%s: bad length %zu", __func__, mlen);
POKE_U32(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
fatal("%s: write: %s", __func__, strerror(errno));
if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen)
fatal("%s: write: %s", __func__, strerror(errno));
}
void
mm_request_receive(int sock, struct sshbuf *m)
{
u_char buf[4], *p = NULL;
u_int msg_len;
int r;
debug3("%s entering", __func__);
if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
if (errno == EPIPE)
cleanup_exit(255);
fatal("%s: read: %s", __func__, strerror(errno));
}
msg_len = PEEK_U32(buf);
if (msg_len > 256 * 1024)
fatal("%s: read: bad msg_len %d", __func__, msg_len);
sshbuf_reset(m);
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (atomicio(read, sock, p, msg_len) != msg_len)
fatal("%s: read: %s", __func__, strerror(errno));
}
void
mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
{
u_char rtype;
int r;
debug3("%s entering: type %d", __func__, type);
mm_request_receive(sock, m);
if ((r = sshbuf_get_u8(m, &rtype)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (rtype != type)
fatal("%s: read: rtype %d != type %d", __func__,
rtype, type);
}
#ifdef WITH_OPENSSL
DH *
mm_choose_dh(int min, int nbits, int max)
{
BIGNUM *p, *g;
int r;
u_char success = 0;
struct sshbuf *m;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u32(m, min)) != 0 ||
(r = sshbuf_put_u32(m, nbits)) != 0 ||
(r = sshbuf_put_u32(m, max)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
if ((r = sshbuf_get_u8(m, &success)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0)
fatal("%s: MONITOR_ANS_MODULI failed", __func__);
- if ((p = BN_new()) == NULL)
- fatal("%s: BN_new failed", __func__);
- if ((g = BN_new()) == NULL)
- fatal("%s: BN_new failed", __func__);
- if ((r = sshbuf_get_bignum2(m, p)) != 0 ||
- (r = sshbuf_get_bignum2(m, g)) != 0)
+ if ((r = sshbuf_get_bignum2(m, &p)) != 0 ||
+ (r = sshbuf_get_bignum2(m, &g)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: remaining %zu", __func__, sshbuf_len(m));
sshbuf_free(m);
return (dh_new_group(g, p));
}
#endif
int
-mm_sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
+mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *hostkey_alg, u_int compat)
{
struct kex *kex = *pmonitor->m_pkex;
struct sshbuf *m;
- u_int ndx = kex->host_key_index(key, 0, active_state);
+ u_int ndx = kex->host_key_index(key, 0, ssh);
int r;
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
(r = sshbuf_put_string(m, data, datalen)) != 0 ||
(r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
(r = sshbuf_put_u32(m, compat)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
return (0);
}
struct passwd *
-mm_getpwnamallow(const char *username)
+mm_getpwnamallow(struct ssh *ssh, const char *username)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshbuf *m;
struct passwd *pw;
size_t len;
u_int i;
ServerOptions *newopts;
int r;
u_char ok;
const u_char *p;
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(m, username)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
if ((r = sshbuf_get_u8(m, &ok)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (ok == 0) {
pw = NULL;
goto out;
}
/* XXX don't like passing struct passwd like this */
pw = xcalloc(sizeof(*pw), 1);
if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (len != sizeof(*pw))
fatal("%s: struct passwd size mismatch", __func__);
memcpy(pw, p, sizeof(*pw));
if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
(r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
(r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
#endif
(r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
out:
/* copy options block as a Match directive may have changed some */
if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (len != sizeof(*newopts))
fatal("%s: option block size mismatch", __func__);
newopts = xcalloc(sizeof(*newopts), 1);
memcpy(newopts, p, sizeof(*newopts));
#define M_CP_STROPT(x) do { \
if (newopts->x != NULL) { \
if ((r = sshbuf_get_cstring(m, \
&newopts->x, NULL)) != 0) \
fatal("%s: buffer error: %s", \
__func__, ssh_err(r)); \
} \
} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
newopts->x = newopts->nx == 0 ? \
NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
for (i = 0; i < newopts->nx; i++) { \
if ((r = sshbuf_get_cstring(m, \
&newopts->x[i], NULL)) != 0) \
fatal("%s: buffer error: %s", \
__func__, ssh_err(r)); \
} \
} while (0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
copy_set_server_options(&options, newopts, 1);
log_change_level(options.log_level);
process_permitopen(ssh, &options);
free(newopts);
sshbuf_free(m);
return (pw);
}
char *
mm_auth2_read_banner(void)
{
struct sshbuf *m;
char *banner;
int r;
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
sshbuf_reset(m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_AUTH2_READ_BANNER, m);
if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
/* treat empty banner as missing banner */
if (strlen(banner) == 0) {
free(banner);
banner = NULL;
}
return (banner);
}
/* Inform the privileged process about service and style */
void
mm_inform_authserv(char *service, char *style)
{
struct sshbuf *m;
int r;
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(m, service)) != 0 ||
(r = sshbuf_put_cstring(m, style ? style : "")) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
sshbuf_free(m);
}
/* Do the password authentication */
int
mm_auth_password(struct ssh *ssh, char *password)
{
struct sshbuf *m;
int r, authenticated = 0;
#ifdef USE_PAM
u_int maxtries = 0;
#endif
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(m, password)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_AUTHPASSWORD, m);
if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#ifdef USE_PAM
if ((r = sshbuf_get_u32(m, &maxtries)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (maxtries > INT_MAX)
fatal("%s: bad maxtries %u", __func__, maxtries);
sshpam_set_maxtries_reached(maxtries);
#endif
sshbuf_free(m);
debug3("%s: user %sauthenticated",
__func__, authenticated ? "" : "not ");
return (authenticated);
}
int
mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
int pubkey_auth_attempt, struct sshauthopt **authoptp)
{
return (mm_key_allowed(MM_USERKEY, NULL, NULL, key,
pubkey_auth_attempt, authoptp));
}
int
-mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
- struct sshkey *key)
+mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
+ const char *user, const char *host, struct sshkey *key)
{
return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL));
}
int
mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp)
{
struct sshbuf *m;
int r, allowed = 0;
struct sshauthopt *opts = NULL;
debug3("%s entering", __func__);
if (authoptp != NULL)
*authoptp = NULL;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u32(m, type)) != 0 ||
(r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
(r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
(r = sshkey_puts(key, m)) != 0 ||
(r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_KEYALLOWED, m);
if ((r = sshbuf_get_u32(m, &allowed)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (allowed && type == MM_USERKEY) {
if ((r = sshauthopt_deserialise(m, &opts)) != 0)
fatal("%s: sshauthopt_deserialise: %s",
__func__, ssh_err(r));
}
sshbuf_free(m);
if (authoptp != NULL) {
*authoptp = opts;
opts = NULL;
}
sshauthopt_free(opts);
return allowed;
}
/*
* This key verify needs to send the key type along, because the
* privileged parent makes the decision if the key is allowed
* for authentication.
*/
int
mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
const u_char *data, size_t datalen, const char *sigalg, u_int compat)
{
struct sshbuf *m;
u_int encoded_ret = 0;
int r;
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshkey_puts(key, m)) != 0 ||
(r = sshbuf_put_string(m, sig, siglen)) != 0 ||
(r = sshbuf_put_string(m, data, datalen)) != 0 ||
(r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_KEYVERIFY, m);
if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
if (encoded_ret != 0)
return SSH_ERR_SIGNATURE_INVALID;
return 0;
}
void
-mm_send_keystate(struct monitor *monitor)
+mm_send_keystate(struct ssh *ssh, struct monitor *monitor)
{
- struct ssh *ssh = active_state; /* XXX */
struct sshbuf *m;
int r;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = ssh_packet_get_state(ssh, m)) != 0)
fatal("%s: get_state failed: %s",
__func__, ssh_err(r));
mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
debug3("%s: Finished sending state", __func__);
sshbuf_free(m);
}
int
mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
{
struct sshbuf *m;
char *p, *msg;
int success = 0, tmp1 = -1, tmp2 = -1, r;
/* Kludge: ensure there are fds free to receive the pty/tty */
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
error("%s: cannot allocate fds for pty", __func__);
if (tmp1 > 0)
close(tmp1);
if (tmp2 > 0)
close(tmp2);
return 0;
}
close(tmp1);
close(tmp2);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
if ((r = sshbuf_get_u32(m, &success)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0) {
debug3("%s: pty alloc failed", __func__);
sshbuf_free(m);
return (0);
}
if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
strlcpy(namebuf, p, namebuflen); /* Possible truncation */
free(p);
if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(msg);
if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
(*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
fatal("%s: receive fds failed", __func__);
/* Success */
return (1);
}
void
mm_session_pty_cleanup2(Session *s)
{
struct sshbuf *m;
int r;
if (s->ttyfd == -1)
return;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
sshbuf_free(m);
/* closed dup'ed master */
if (s->ptymaster != -1 && close(s->ptymaster) < 0)
error("close(s->ptymaster/%d): %s",
s->ptymaster, strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
}
#ifdef USE_PAM
void
-mm_start_pam(Authctxt *authctxt)
+mm_start_pam(struct ssh *ssh)
{
struct sshbuf *m;
debug3("%s entering", __func__);
if (!options.use_pam)
fatal("UsePAM=no, but ended up in %s anyway", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m);
sshbuf_free(m);
}
u_int
mm_do_pam_account(void)
{
struct sshbuf *m;
u_int ret;
char *msg;
size_t msglen;
int r;
debug3("%s entering", __func__);
if (!options.use_pam)
fatal("UsePAM=no, but ended up in %s anyway", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_PAM_ACCOUNT, m);
if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
(r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 ||
(r = sshbuf_put(loginmsg, msg, msglen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(msg);
sshbuf_free(m);
debug3("%s returning %d", __func__, ret);
return (ret);
}
void *
mm_sshpam_init_ctx(Authctxt *authctxt)
{
struct sshbuf *m;
int r, success;
debug3("%s", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m);
debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_PAM_INIT_CTX, m);
if ((r = sshbuf_get_u32(m, &success)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0) {
debug3("%s: pam_init_ctx failed", __func__);
sshbuf_free(m);
return (NULL);
}
sshbuf_free(m);
return (authctxt);
}
int
mm_sshpam_query(void *ctx, char **name, char **info,
u_int *num, char ***prompts, u_int **echo_on)
{
struct sshbuf *m;
u_int i, n;
int r, ret;
debug3("%s", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m);
debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m);
if ((r = sshbuf_get_u32(m, &ret)) != 0 ||
(r = sshbuf_get_cstring(m, name, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, info, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &n)) != 0 ||
(r = sshbuf_get_u32(m, num)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("%s: pam_query returned %d", __func__, ret);
sshpam_set_maxtries_reached(n);
if (*num > PAM_MAX_NUM_MSG)
fatal("%s: received %u PAM messages, expected <= %u",
__func__, *num, PAM_MAX_NUM_MSG);
*prompts = xcalloc((*num + 1), sizeof(char *));
*echo_on = xcalloc((*num + 1), sizeof(u_int));
for (i = 0; i < *num; ++i) {
if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 ||
(r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
sshbuf_free(m);
return (ret);
}
int
mm_sshpam_respond(void *ctx, u_int num, char **resp)
{
struct sshbuf *m;
u_int n, i;
int r, ret;
debug3("%s", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u32(m, num)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; i < num; ++i) {
if ((r = sshbuf_put_cstring(m, resp[i])) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m);
debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_PAM_RESPOND, m);
if ((r = sshbuf_get_u32(m, &n)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
ret = (int)n; /* XXX */
debug3("%s: pam_respond returned %d", __func__, ret);
sshbuf_free(m);
return (ret);
}
void
mm_sshpam_free_ctx(void *ctxtp)
{
struct sshbuf *m;
debug3("%s", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m);
debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_PAM_FREE_CTX, m);
sshbuf_free(m);
}
#endif /* USE_PAM */
/* Request process termination */
void
mm_terminate(void)
{
struct sshbuf *m;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
sshbuf_free(m);
}
static void
mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
char ***prompts, u_int **echo_on)
{
*name = xstrdup("");
*infotxt = xstrdup("");
*numprompts = 1;
*prompts = xcalloc(*numprompts, sizeof(char *));
*echo_on = xcalloc(*numprompts, sizeof(u_int));
(*echo_on)[0] = 0;
}
int
mm_bsdauth_query(void *ctx, char **name, char **infotxt,
u_int *numprompts, char ***prompts, u_int **echo_on)
{
struct sshbuf *m;
u_int success;
char *challenge;
int r;
debug3("%s: entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_BSDAUTHQUERY, m);
if ((r = sshbuf_get_u32(m, &success)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (success == 0) {
debug3("%s: no challenge", __func__);
sshbuf_free(m);
return (-1);
}
/* Get the challenge, and format the response */
if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
(*prompts)[0] = challenge;
debug3("%s: received challenge: %s", __func__, challenge);
return (0);
}
int
mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
{
struct sshbuf *m;
int r, authok;
debug3("%s: entering", __func__);
if (numresponses != 1)
return (-1);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_BSDAUTHRESPOND, m);
if ((r = sshbuf_get_u32(m, &authok)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
return ((authok == 0) ? -1 : 0);
}
#ifdef SSH_AUDIT_EVENTS
void
-mm_audit_event(ssh_audit_event_t event)
+mm_audit_event(struct ssh *ssh, ssh_audit_event_t event)
{
struct sshbuf *m;
int r;
debug3("%s entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u32(m, event)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m);
sshbuf_free(m);
}
void
mm_audit_run_command(const char *command)
{
struct sshbuf *m;
int r;
debug3("%s entering command %s", __func__, command);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(m, command)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m);
sshbuf_free(m);
}
#endif /* SSH_AUDIT_EVENTS */
#ifdef GSSAPI
OM_uint32
mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
{
struct sshbuf *m;
OM_uint32 major;
int r;
/* Client doesn't get to see the context */
*ctx = NULL;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
if ((r = sshbuf_get_u32(m, &major)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
return (major);
}
OM_uint32
mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
gss_buffer_desc *out, OM_uint32 *flagsp)
{
struct sshbuf *m;
OM_uint32 major;
u_int flags;
int r;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
if ((r = sshbuf_get_u32(m, &major)) != 0 ||
(r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (flagsp != NULL) {
if ((r = sshbuf_get_u32(m, &flags)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
*flagsp = flags;
}
sshbuf_free(m);
return (major);
}
OM_uint32
mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
{
struct sshbuf *m;
OM_uint32 major;
int r;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
(r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_GSSCHECKMIC, m);
if ((r = sshbuf_get_u32(m, &major)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
return(major);
}
int
mm_ssh_gssapi_userok(char *user)
{
struct sshbuf *m;
int r, authenticated = 0;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_GSSUSEROK, m);
if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(m);
debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
return (authenticated);
}
#endif /* GSSAPI */
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 644da081db8d..fdebb3aa47e0 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,100 +1,98 @@
-/* $OpenBSD: monitor_wrap.h,v 1.38 2018/07/11 18:53:29 markus Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.41 2019/01/19 21:43:56 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MM_WRAP_H_
#define _MM_WRAP_H_
extern int use_privsep;
#define PRIVSEP(x) (use_privsep ? mm_##x : x)
enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY };
+struct ssh;
struct monitor;
struct Authctxt;
struct sshkey;
struct sshauthopt;
void mm_log_handler(LogLevel, const char *, void *);
int mm_is_monitor(void);
DH *mm_choose_dh(int, int, int);
-int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t,
- const char *, u_int compat);
+int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
+ const u_char *, size_t, const char *, u_int compat);
void mm_inform_authserv(char *, char *);
-struct passwd *mm_getpwnamallow(const char *);
+struct passwd *mm_getpwnamallow(struct ssh *, const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct ssh *, char *);
int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *,
int, struct sshauthopt **);
int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int,
struct sshauthopt **);
-int mm_hostbased_key_allowed(struct passwd *, const char *,
+int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *,
const char *, struct sshkey *);
int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
const u_char *, size_t, const char *, u_int);
#ifdef GSSAPI
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
int mm_ssh_gssapi_userok(char *user);
OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
#endif
#ifdef USE_PAM
-void mm_start_pam(struct Authctxt *);
+void mm_start_pam(struct ssh *ssh);
u_int mm_do_pam_account(void);
void *mm_sshpam_init_ctx(struct Authctxt *);
int mm_sshpam_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_sshpam_respond(void *, u_int, char **);
void mm_sshpam_free_ctx(void *);
#endif
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
-void mm_audit_event(ssh_audit_event_t);
+void mm_audit_event(struct ssh *, ssh_audit_event_t);
void mm_audit_run_command(const char *);
#endif
struct Session;
void mm_terminate(void);
int mm_pty_allocate(int *, int *, char *, size_t);
void mm_session_pty_cleanup2(struct Session *);
/* Key export functions */
struct newkeys *mm_newkeys_from_blob(u_char *, int);
int mm_newkeys_to_blob(int, u_char **, u_int *);
-void monitor_clear_keystate(struct monitor *);
-void monitor_apply_keystate(struct monitor *);
-void mm_get_keystate(struct monitor *);
-void mm_send_keystate(struct monitor*);
+void mm_send_keystate(struct ssh *, struct monitor*);
/* bsdauth */
int mm_bsdauth_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_bsdauth_respond(void *, u_int, char **);
#endif /* _MM_WRAP_H_ */
diff --git a/mux.c b/mux.c
index 8e4b60827fc8..e89db193de3a 100644
--- a/mux.c
+++ b/mux.c
@@ -1,2391 +1,2401 @@
-/* $OpenBSD: mux.c,v 1.77 2018/09/26 07:32:44 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.79 2019/01/19 21:35:25 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* ssh session multiplexing support */
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#else
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
#endif
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "log.h"
#include "ssh.h"
#include "ssh2.h"
#include "pathnames.h"
#include "misc.h"
#include "match.h"
#include "sshbuf.h"
#include "channels.h"
#include "msg.h"
#include "packet.h"
#include "monitor_fdpass.h"
#include "sshpty.h"
#include "sshkey.h"
#include "readconf.h"
#include "clientloop.h"
#include "ssherr.h"
/* from ssh.c */
extern int tty_flag;
extern Options options;
extern int stdin_null_flag;
extern char *host;
extern int subsystem_flag;
extern struct sshbuf *command;
extern volatile sig_atomic_t quit_pending;
/* Context for session open confirmation callback */
struct mux_session_confirm_ctx {
u_int want_tty;
u_int want_subsys;
u_int want_x_fwd;
u_int want_agent_fwd;
struct sshbuf *cmd;
char *term;
struct termios tio;
char **env;
u_int rid;
};
/* Context for stdio fwd open confirmation callback */
struct mux_stdio_confirm_ctx {
u_int rid;
};
/* Context for global channel callback */
struct mux_channel_confirm_ctx {
u_int cid; /* channel id */
u_int rid; /* request id */
int fid; /* forward id */
};
/* fd to control socket */
int muxserver_sock = -1;
/* client request id */
u_int muxclient_request_id = 0;
/* Multiplexing control command */
u_int muxclient_command = 0;
/* Set when signalled. */
static volatile sig_atomic_t muxclient_terminate = 0;
/* PID of multiplex server */
static u_int muxserver_pid = 0;
static Channel *mux_listener_channel = NULL;
struct mux_master_state {
int hello_rcvd;
};
/* mux protocol messages */
#define MUX_MSG_HELLO 0x00000001
#define MUX_C_NEW_SESSION 0x10000002
#define MUX_C_ALIVE_CHECK 0x10000004
#define MUX_C_TERMINATE 0x10000005
#define MUX_C_OPEN_FWD 0x10000006
#define MUX_C_CLOSE_FWD 0x10000007
#define MUX_C_NEW_STDIO_FWD 0x10000008
#define MUX_C_STOP_LISTENING 0x10000009
#define MUX_C_PROXY 0x1000000f
#define MUX_S_OK 0x80000001
#define MUX_S_PERMISSION_DENIED 0x80000002
#define MUX_S_FAILURE 0x80000003
#define MUX_S_EXIT_MESSAGE 0x80000004
#define MUX_S_ALIVE 0x80000005
#define MUX_S_SESSION_OPENED 0x80000006
#define MUX_S_REMOTE_PORT 0x80000007
#define MUX_S_TTY_ALLOC_FAIL 0x80000008
#define MUX_S_PROXY 0x8000000f
/* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
#define MUX_FWD_LOCAL 1
#define MUX_FWD_REMOTE 2
#define MUX_FWD_DYNAMIC 3
static void mux_session_confirm(struct ssh *, int, int, void *);
static void mux_stdio_confirm(struct ssh *, int, int, void *);
static int mux_master_process_hello(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_new_session(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_alive_check(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_terminate(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_open_fwd(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_close_fwd(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_stdio_fwd(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_stop_listening(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int mux_master_process_proxy(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static const struct {
u_int type;
int (*handler)(struct ssh *, u_int, Channel *,
struct sshbuf *, struct sshbuf *);
} mux_master_handlers[] = {
{ MUX_MSG_HELLO, mux_master_process_hello },
{ MUX_C_NEW_SESSION, mux_master_process_new_session },
{ MUX_C_ALIVE_CHECK, mux_master_process_alive_check },
{ MUX_C_TERMINATE, mux_master_process_terminate },
{ MUX_C_OPEN_FWD, mux_master_process_open_fwd },
{ MUX_C_CLOSE_FWD, mux_master_process_close_fwd },
{ MUX_C_NEW_STDIO_FWD, mux_master_process_stdio_fwd },
{ MUX_C_STOP_LISTENING, mux_master_process_stop_listening },
{ MUX_C_PROXY, mux_master_process_proxy },
{ 0, NULL }
};
/* Cleanup callback fired on closure of mux slave _session_ channel */
/* ARGSUSED */
static void
mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{
Channel *cc, *c = channel_by_id(ssh, cid);
debug3("%s: entering for channel %d", __func__, cid);
if (c == NULL)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
if (c->ctl_chan != -1) {
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing control channel %d",
__func__, c->self, c->ctl_chan);
c->ctl_chan = -1;
cc->remote_id = 0;
cc->have_remote_id = 0;
chan_rcvd_oclose(ssh, cc);
}
channel_cancel_cleanup(ssh, c->self);
}
/* Cleanup callback fired on closure of mux slave _control_ channel */
/* ARGSUSED */
static void
mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{
Channel *sc, *c = channel_by_id(ssh, cid);
debug3("%s: entering for channel %d", __func__, cid);
if (c == NULL)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
if (c->have_remote_id) {
if ((sc = channel_by_id(ssh, c->remote_id)) == NULL)
fatal("%s: channel %d missing session channel %u",
__func__, c->self, c->remote_id);
c->remote_id = 0;
c->have_remote_id = 0;
sc->ctl_chan = -1;
if (sc->type != SSH_CHANNEL_OPEN &&
sc->type != SSH_CHANNEL_OPENING) {
debug2("%s: channel %d: not open", __func__, sc->self);
chan_mark_dead(ssh, sc);
} else {
if (sc->istate == CHAN_INPUT_OPEN)
chan_read_failed(ssh, sc);
if (sc->ostate == CHAN_OUTPUT_OPEN)
chan_write_failed(ssh, sc);
}
}
channel_cancel_cleanup(ssh, c->self);
}
/* Check mux client environment variables before passing them to mux master. */
static int
env_permitted(char *env)
{
int i, ret;
char name[1024], *cp;
if ((cp = strchr(env, '=')) == NULL || cp == env)
return 0;
ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
if (ret <= 0 || (size_t)ret >= sizeof(name)) {
error("%s: name '%.100s...' too long", __func__, env);
return 0;
}
for (i = 0; i < options.num_send_env; i++)
if (match_pattern(name, options.send_env[i]))
return 1;
return 0;
}
/* Mux master protocol message handlers */
static int
mux_master_process_hello(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
u_int ver;
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
int r;
if (state == NULL)
fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
if (state->hello_rcvd) {
error("%s: HELLO received twice", __func__);
return -1;
}
if ((r = sshbuf_get_u32(m, &ver)) != 0) {
error("%s: malformed message: %s", __func__, ssh_err(r));
return -1;
}
if (ver != SSHMUX_VER) {
error("%s: unsupported multiplexing protocol version %u "
"(expected %u)", __func__, ver, SSHMUX_VER);
return -1;
}
debug2("%s: channel %d slave version %u", __func__, c->self, ver);
/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
char *name = NULL;
size_t value_len = 0;
if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
(r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) {
error("%s: malformed extension: %s",
__func__, ssh_err(r));
return -1;
}
debug2("%s: Unrecognised extension \"%s\" length %zu",
__func__, name, value_len);
free(name);
}
state->hello_rcvd = 1;
return 0;
}
/* Enqueue a "ok" response to the reply buffer */
static void
reply_ok(struct sshbuf *reply, u_int rid)
{
int r;
if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
}
/* Enqueue an error response to the reply buffer */
static void
reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg)
{
int r;
if ((r = sshbuf_put_u32(reply, type)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_cstring(reply, msg)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
}
static int
mux_master_process_new_session(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
Channel *nc;
struct mux_session_confirm_ctx *cctx;
char *cmd, *cp;
u_int i, j, env_len, escape_char, window, packetmax;
int r, new_fd[3];
/* Reply for SSHMUX_COMMAND_OPEN */
cctx = xcalloc(1, sizeof(*cctx));
cctx->term = NULL;
cctx->rid = rid;
cmd = NULL;
cctx->env = NULL;
env_len = 0;
if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */
(r = sshbuf_get_u32(m, &cctx->want_tty)) != 0 ||
(r = sshbuf_get_u32(m, &cctx->want_x_fwd)) != 0 ||
(r = sshbuf_get_u32(m, &cctx->want_agent_fwd)) != 0 ||
(r = sshbuf_get_u32(m, &cctx->want_subsys)) != 0 ||
(r = sshbuf_get_u32(m, &escape_char)) != 0 ||
(r = sshbuf_get_cstring(m, &cctx->term, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) {
malf:
free(cmd);
for (j = 0; j < env_len; j++)
free(cctx->env[j]);
free(cctx->env);
free(cctx->term);
free(cctx);
error("%s: malformed message", __func__);
return -1;
}
#define MUX_MAX_ENV_VARS 4096
while (sshbuf_len(m) > 0) {
if ((r = sshbuf_get_cstring(m, &cp, NULL)) != 0)
goto malf;
if (!env_permitted(cp)) {
free(cp);
continue;
}
cctx->env = xreallocarray(cctx->env, env_len + 2,
sizeof(*cctx->env));
cctx->env[env_len++] = cp;
cctx->env[env_len] = NULL;
if (env_len > MUX_MAX_ENV_VARS) {
error("%s: >%d environment variables received, "
"ignoring additional", __func__, MUX_MAX_ENV_VARS);
break;
}
}
debug2("%s: channel %d: request tty %d, X %d, agent %d, subsys %d, "
"term \"%s\", cmd \"%s\", env %u", __func__, c->self,
cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
cctx->want_subsys, cctx->term, cmd, env_len);
if ((cctx->cmd = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0)
fatal("%s: sshbuf_put: %s", __func__, ssh_err(r));
free(cmd);
cmd = NULL;
/* Gather fds from client */
for(i = 0; i < 3; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
error("%s: failed to receive fd %d from slave",
__func__, i);
for (j = 0; j < i; j++)
close(new_fd[j]);
for (j = 0; j < env_len; j++)
free(cctx->env[j]);
free(cctx->env);
free(cctx->term);
sshbuf_free(cctx->cmd);
free(cctx);
reply_error(reply, MUX_S_FAILURE, rid,
"did not receive file descriptors");
return -1;
}
}
debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
new_fd[0], new_fd[1], new_fd[2]);
/* XXX support multiple child sessions in future */
if (c->have_remote_id) {
debug2("%s: session already open", __func__);
reply_error(reply, MUX_S_FAILURE, rid,
"Multiple sessions not supported");
cleanup:
close(new_fd[0]);
close(new_fd[1]);
close(new_fd[2]);
free(cctx->term);
if (env_len != 0) {
for (i = 0; i < env_len; i++)
free(cctx->env[i]);
free(cctx->env);
}
sshbuf_free(cctx->cmd);
free(cctx);
return 0;
}
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow shared connection to %s? ", host)) {
debug2("%s: session refused by user", __func__);
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto cleanup;
}
}
/* Try to pick up ttymodes from client before it goes raw */
if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
error("%s: tcgetattr: %s", __func__, strerror(errno));
/* enable nonblocking unless tty */
if (!isatty(new_fd[0]))
set_nonblock(new_fd[0]);
if (!isatty(new_fd[1]))
set_nonblock(new_fd[1]);
if (!isatty(new_fd[2]))
set_nonblock(new_fd[2]);
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
if (cctx->want_tty) {
window >>= 1;
packetmax >>= 1;
}
nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
new_fd[0], new_fd[1], new_fd[2], window, packetmax,
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
if (cctx->want_tty && escape_char != 0xffffffff) {
channel_register_filter(ssh, nc->self,
client_simple_escape_filter, NULL,
client_filter_cleanup,
client_new_escape_filter_ctx((int)escape_char));
}
debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan);
channel_send_open(ssh, nc->self);
channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx);
c->mux_pause = 1; /* stop handling messages until open_confirm done */
channel_register_cleanup(ssh, nc->self,
mux_master_session_cleanup_cb, 1);
/* reply is deferred, sent by mux_session_confirm */
return 0;
}
static int
mux_master_process_alive_check(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
int r;
debug2("%s: channel %d: alive check", __func__, c->self);
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_u32(reply, (u_int)getpid())) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
return 0;
}
static int
mux_master_process_terminate(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
debug2("%s: channel %d: terminate request", __func__, c->self);
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Terminate shared connection to %s? ",
host)) {
debug2("%s: termination refused by user", __func__);
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
return 0;
}
}
quit_pending = 1;
reply_ok(reply, rid);
/* XXX exit happens too soon - message never makes it to client */
return 0;
}
static char *
format_forward(u_int ftype, struct Forward *fwd)
{
char *ret;
switch (ftype) {
case MUX_FWD_LOCAL:
xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
(fwd->listen_path != NULL) ? fwd->listen_path :
(fwd->listen_host == NULL) ?
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
fwd->listen_host, fwd->listen_port,
(fwd->connect_path != NULL) ? fwd->connect_path :
fwd->connect_host, fwd->connect_port);
break;
case MUX_FWD_DYNAMIC:
xasprintf(&ret, "dynamic forward %.200s:%d -> *",
(fwd->listen_host == NULL) ?
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
fwd->listen_host, fwd->listen_port);
break;
case MUX_FWD_REMOTE:
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
(fwd->listen_path != NULL) ? fwd->listen_path :
(fwd->listen_host == NULL) ?
"LOCALHOST" : fwd->listen_host,
fwd->listen_port,
(fwd->connect_path != NULL) ? fwd->connect_path :
fwd->connect_host, fwd->connect_port);
break;
default:
fatal("%s: unknown forward type %u", __func__, ftype);
}
return ret;
}
static int
compare_host(const char *a, const char *b)
{
if (a == NULL && b == NULL)
return 1;
if (a == NULL || b == NULL)
return 0;
return strcmp(a, b) == 0;
}
static int
compare_forward(struct Forward *a, struct Forward *b)
{
if (!compare_host(a->listen_host, b->listen_host))
return 0;
if (!compare_host(a->listen_path, b->listen_path))
return 0;
if (a->listen_port != b->listen_port)
return 0;
if (!compare_host(a->connect_host, b->connect_host))
return 0;
if (!compare_host(a->connect_path, b->connect_path))
return 0;
if (a->connect_port != b->connect_port)
return 0;
return 1;
}
static void
mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
{
struct mux_channel_confirm_ctx *fctx = ctxt;
char *failmsg = NULL;
struct Forward *rfwd;
Channel *c;
struct sshbuf *out;
+ u_int port;
int r;
if ((c = channel_by_id(ssh, fctx->cid)) == NULL) {
/* no channel for reply */
error("%s: unknown channel", __func__);
return;
}
if ((out = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if (fctx->fid >= options.num_remote_forwards ||
(options.remote_forwards[fctx->fid].connect_path == NULL &&
options.remote_forwards[fctx->fid].connect_host == NULL)) {
xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid);
goto fail;
}
rfwd = &options.remote_forwards[fctx->fid];
debug("%s: %s for: listen %d, connect %s:%d", __func__,
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS) {
if (rfwd->listen_port == 0) {
- rfwd->allocated_port = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &port)) != 0)
+ fatal("%s: packet error: %s",
+ __func__, ssh_err(r));
+ if (port > 65535) {
+ fatal("Invalid allocated port %u for "
+ "mux remote forward to %s:%d", port,
+ rfwd->connect_host, rfwd->connect_port);
+ }
+ rfwd->allocated_port = (int)port;
debug("Allocated port %u for mux remote forward"
" to %s:%d", rfwd->allocated_port,
rfwd->connect_host, rfwd->connect_port);
if ((r = sshbuf_put_u32(out,
MUX_S_REMOTE_PORT)) != 0 ||
(r = sshbuf_put_u32(out, fctx->rid)) != 0 ||
(r = sshbuf_put_u32(out,
rfwd->allocated_port)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
channel_update_permission(ssh, rfwd->handle,
rfwd->allocated_port);
} else {
reply_ok(out, fctx->rid);
}
goto out;
} else {
if (rfwd->listen_port == 0)
channel_update_permission(ssh, rfwd->handle, -1);
if (rfwd->listen_path != NULL)
xasprintf(&failmsg, "remote port forwarding failed for "
"listen path %s", rfwd->listen_path);
else
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
debug2("%s: clearing registered forwarding for listen %d, "
"connect %s:%d", __func__, rfwd->listen_port,
rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
free(rfwd->listen_host);
free(rfwd->listen_path);
free(rfwd->connect_host);
free(rfwd->connect_path);
memset(rfwd, 0, sizeof(*rfwd));
}
fail:
error("%s: %s", __func__, failmsg);
reply_error(out, MUX_S_FAILURE, fctx->rid, failmsg);
free(failmsg);
out:
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
sshbuf_free(out);
if (c->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, c->mux_pause);
c->mux_pause = 0; /* start processing messages again */
}
static int
mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
struct Forward fwd;
char *fwd_desc = NULL;
char *listen_addr, *connect_addr;
u_int ftype;
u_int lport, cport;
int r, i, ret = 0, freefwd = 1;
memset(&fwd, 0, sizeof(fwd));
/* XXX - lport/cport check redundant */
if ((r = sshbuf_get_u32(m, &ftype)) != 0 ||
(r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &lport)) != 0 ||
(r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__);
ret = -1;
goto out;
}
if (*listen_addr == '\0') {
free(listen_addr);
listen_addr = NULL;
}
if (*connect_addr == '\0') {
free(connect_addr);
connect_addr = NULL;
}
memset(&fwd, 0, sizeof(fwd));
fwd.listen_port = lport;
if (fwd.listen_port == PORT_STREAMLOCAL)
fwd.listen_path = listen_addr;
else
fwd.listen_host = listen_addr;
fwd.connect_port = cport;
if (fwd.connect_port == PORT_STREAMLOCAL)
fwd.connect_path = connect_addr;
else
fwd.connect_host = connect_addr;
debug2("%s: channel %d: request %s", __func__, c->self,
(fwd_desc = format_forward(ftype, &fwd)));
if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE &&
ftype != MUX_FWD_DYNAMIC) {
logit("%s: invalid forwarding type %u", __func__, ftype);
invalid:
free(listen_addr);
free(connect_addr);
reply_error(reply, MUX_S_FAILURE, rid,
"Invalid forwarding request");
return 0;
}
if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
logit("%s: streamlocal and dynamic forwards "
"are mutually exclusive", __func__);
goto invalid;
}
if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
logit("%s: invalid listen port %u", __func__,
fwd.listen_port);
goto invalid;
}
if ((fwd.connect_port != PORT_STREAMLOCAL &&
fwd.connect_port >= 65536) ||
(ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE &&
fwd.connect_port == 0)) {
logit("%s: invalid connect port %u", __func__,
fwd.connect_port);
goto invalid;
}
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL &&
fwd.connect_path == NULL) {
logit("%s: missing connect host", __func__);
goto invalid;
}
/* Skip forwards that have already been requested */
switch (ftype) {
case MUX_FWD_LOCAL:
case MUX_FWD_DYNAMIC:
for (i = 0; i < options.num_local_forwards; i++) {
if (compare_forward(&fwd,
options.local_forwards + i)) {
exists:
debug2("%s: found existing forwarding",
__func__);
reply_ok(reply, rid);
goto out;
}
}
break;
case MUX_FWD_REMOTE:
for (i = 0; i < options.num_remote_forwards; i++) {
if (!compare_forward(&fwd, options.remote_forwards + i))
continue;
if (fwd.listen_port != 0)
goto exists;
debug2("%s: found allocated port", __func__);
if ((r = sshbuf_put_u32(reply,
MUX_S_REMOTE_PORT)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_u32(reply,
options.remote_forwards[i].allocated_port)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
goto out;
}
break;
}
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Open %s on %s?", fwd_desc, host)) {
debug2("%s: forwarding refused by user", __func__);
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto out;
}
}
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) {
fail:
logit("%s: requested %s failed", __func__, fwd_desc);
reply_error(reply, MUX_S_FAILURE, rid,
"Port forwarding failed");
goto out;
}
add_local_forward(&options, &fwd);
freefwd = 0;
} else {
struct mux_channel_confirm_ctx *fctx;
fwd.handle = channel_request_remote_forwarding(ssh, &fwd);
if (fwd.handle < 0)
goto fail;
add_remote_forward(&options, &fwd);
fctx = xcalloc(1, sizeof(*fctx));
fctx->cid = c->self;
fctx->rid = rid;
fctx->fid = options.num_remote_forwards - 1;
client_register_global_confirm(mux_confirm_remote_forward,
fctx);
freefwd = 0;
c->mux_pause = 1; /* wait for mux_confirm_remote_forward */
/* delayed reply in mux_confirm_remote_forward */
goto out;
}
reply_ok(reply, rid);
out:
free(fwd_desc);
if (freefwd) {
free(fwd.listen_host);
free(fwd.listen_path);
free(fwd.connect_host);
free(fwd.connect_path);
}
return ret;
}
static int
mux_master_process_close_fwd(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
struct Forward fwd, *found_fwd;
char *fwd_desc = NULL;
const char *error_reason = NULL;
char *listen_addr = NULL, *connect_addr = NULL;
u_int ftype;
int r, i, ret = 0;
u_int lport, cport;
memset(&fwd, 0, sizeof(fwd));
if ((r = sshbuf_get_u32(m, &ftype)) != 0 ||
(r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &lport)) != 0 ||
(r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
error("%s: malformed message", __func__);
ret = -1;
goto out;
}
if (*listen_addr == '\0') {
free(listen_addr);
listen_addr = NULL;
}
if (*connect_addr == '\0') {
free(connect_addr);
connect_addr = NULL;
}
memset(&fwd, 0, sizeof(fwd));
fwd.listen_port = lport;
if (fwd.listen_port == PORT_STREAMLOCAL)
fwd.listen_path = listen_addr;
else
fwd.listen_host = listen_addr;
fwd.connect_port = cport;
if (fwd.connect_port == PORT_STREAMLOCAL)
fwd.connect_path = connect_addr;
else
fwd.connect_host = connect_addr;
debug2("%s: channel %d: request cancel %s", __func__, c->self,
(fwd_desc = format_forward(ftype, &fwd)));
/* make sure this has been requested */
found_fwd = NULL;
switch (ftype) {
case MUX_FWD_LOCAL:
case MUX_FWD_DYNAMIC:
for (i = 0; i < options.num_local_forwards; i++) {
if (compare_forward(&fwd,
options.local_forwards + i)) {
found_fwd = options.local_forwards + i;
break;
}
}
break;
case MUX_FWD_REMOTE:
for (i = 0; i < options.num_remote_forwards; i++) {
if (compare_forward(&fwd,
options.remote_forwards + i)) {
found_fwd = options.remote_forwards + i;
break;
}
}
break;
}
if (found_fwd == NULL)
error_reason = "port not forwarded";
else if (ftype == MUX_FWD_REMOTE) {
/*
* This shouldn't fail unless we confused the host/port
* between options.remote_forwards and permitted_opens.
* However, for dynamic allocated listen ports we need
* to use the actual listen port.
*/
if (channel_request_rforward_cancel(ssh, found_fwd) == -1)
error_reason = "port not in permitted opens";
} else { /* local and dynamic forwards */
/* Ditto */
if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port,
&options.fwd_opts) == -1)
error_reason = "port not found";
}
if (error_reason != NULL)
reply_error(reply, MUX_S_FAILURE, rid, error_reason);
else {
reply_ok(reply, rid);
free(found_fwd->listen_host);
free(found_fwd->listen_path);
free(found_fwd->connect_host);
free(found_fwd->connect_path);
found_fwd->listen_host = found_fwd->connect_host = NULL;
found_fwd->listen_path = found_fwd->connect_path = NULL;
found_fwd->listen_port = found_fwd->connect_port = 0;
}
out:
free(fwd_desc);
free(listen_addr);
free(connect_addr);
return ret;
}
static int
mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
Channel *nc;
char *chost = NULL;
u_int cport, i, j;
int r, new_fd[2];
struct mux_stdio_confirm_ctx *cctx;
if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &cport)) != 0) {
free(chost);
error("%s: malformed message", __func__);
return -1;
}
debug2("%s: channel %d: request stdio fwd to %s:%u",
__func__, c->self, chost, cport);
/* Gather fds from client */
for(i = 0; i < 2; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
error("%s: failed to receive fd %d from slave",
__func__, i);
for (j = 0; j < i; j++)
close(new_fd[j]);
free(chost);
/* prepare reply */
reply_error(reply, MUX_S_FAILURE, rid,
"did not receive file descriptors");
return -1;
}
}
debug3("%s: got fds stdin %d, stdout %d", __func__,
new_fd[0], new_fd[1]);
/* XXX support multiple child sessions in future */
if (c->have_remote_id) {
debug2("%s: session already open", __func__);
reply_error(reply, MUX_S_FAILURE, rid,
"Multiple sessions not supported");
cleanup:
close(new_fd[0]);
close(new_fd[1]);
free(chost);
return 0;
}
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow forward to %s:%u? ",
chost, cport)) {
debug2("%s: stdio fwd refused by user", __func__);
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto cleanup;
}
}
/* enable nonblocking unless tty */
if (!isatty(new_fd[0]))
set_nonblock(new_fd[0]);
if (!isatty(new_fd[1]))
set_nonblock(new_fd[1]);
nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
free(chost);
nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan);
channel_register_cleanup(ssh, nc->self,
mux_master_session_cleanup_cb, 1);
cctx = xcalloc(1, sizeof(*cctx));
cctx->rid = rid;
channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx);
c->mux_pause = 1; /* stop handling messages until open_confirm done */
/* reply is deferred, sent by mux_session_confirm */
return 0;
}
/* Callback on open confirmation in mux master for a mux stdio fwd session. */
static void
mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
{
struct mux_stdio_confirm_ctx *cctx = arg;
Channel *c, *cc;
struct sshbuf *reply;
int r;
if (cctx == NULL)
fatal("%s: cctx == NULL", __func__);
if ((c = channel_by_id(ssh, id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan);
if ((reply = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if (!success) {
debug3("%s: sending failure reply", __func__);
reply_error(reply, MUX_S_FAILURE, cctx->rid,
"Session open refused by peer");
/* prepare reply */
goto done;
}
debug3("%s: sending success reply", __func__);
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
(r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
(r = sshbuf_put_u32(reply, c->self)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
done:
/* Send reply */
if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
sshbuf_free(reply);
if (cc->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
free(cctx);
}
static int
mux_master_process_stop_listening(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
debug("%s: channel %d: stop listening", __func__, c->self);
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Disable further multiplexing on shared "
"connection to %s? ", host)) {
debug2("%s: stop listen refused by user", __func__);
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
return 0;
}
}
if (mux_listener_channel != NULL) {
channel_free(ssh, mux_listener_channel);
client_stop_mux();
free(options.control_path);
options.control_path = NULL;
mux_listener_channel = NULL;
muxserver_sock = -1;
}
reply_ok(reply, rid);
return 0;
}
static int
mux_master_process_proxy(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
int r;
debug("%s: channel %d: proxy request", __func__, c->self);
c->mux_rcb = channel_proxy_downstream;
if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
return 0;
}
/* Channel callbacks fired on read/write from mux slave fd */
static int
mux_master_read_cb(struct ssh *ssh, Channel *c)
{
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
struct sshbuf *in = NULL, *out = NULL;
u_int type, rid, i;
int r, ret = -1;
if ((out = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
/* Setup ctx and */
if (c->mux_ctx == NULL) {
state = xcalloc(1, sizeof(*state));
c->mux_ctx = state;
channel_register_cleanup(ssh, c->self,
mux_master_control_cleanup_cb, 0);
/* Send hello */
if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 ||
(r = sshbuf_put_u32(out, SSHMUX_VER)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
/* no extensions */
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
fatal("%s: sshbuf_put_stringb: %s",
__func__, ssh_err(r));
debug3("%s: channel %d: hello sent", __func__, c->self);
ret = 0;
goto out;
}
/* Channel code ensures that we receive whole packets */
if ((r = sshbuf_froms(c->input, &in)) != 0) {
malf:
error("%s: malformed message", __func__);
goto out;
}
if ((r = sshbuf_get_u32(in, &type)) != 0)
goto malf;
debug3("%s: channel %d packet type 0x%08x len %zu",
__func__, c->self, type, sshbuf_len(in));
if (type == MUX_MSG_HELLO)
rid = 0;
else {
if (!state->hello_rcvd) {
error("%s: expected MUX_MSG_HELLO(0x%08x), "
"received 0x%08x", __func__, MUX_MSG_HELLO, type);
goto out;
}
if ((r = sshbuf_get_u32(in, &rid)) != 0)
goto malf;
}
for (i = 0; mux_master_handlers[i].handler != NULL; i++) {
if (type == mux_master_handlers[i].type) {
ret = mux_master_handlers[i].handler(ssh, rid,
c, in, out);
break;
}
}
if (mux_master_handlers[i].handler == NULL) {
error("%s: unsupported mux message 0x%08x", __func__, type);
reply_error(out, MUX_S_FAILURE, rid, "unsupported request");
ret = 0;
}
/* Enqueue reply packet */
if (sshbuf_len(out) != 0) {
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
fatal("%s: sshbuf_put_stringb: %s",
__func__, ssh_err(r));
}
out:
sshbuf_free(in);
sshbuf_free(out);
return ret;
}
void
mux_exit_message(struct ssh *ssh, Channel *c, int exitval)
{
struct sshbuf *m;
Channel *mux_chan;
int r;
debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
exitval);
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_S_EXIT_MESSAGE)) != 0 ||
(r = sshbuf_put_u32(m, c->self)) != 0 ||
(r = sshbuf_put_u32(m, exitval)) != 0 ||
(r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
sshbuf_free(m);
}
void
mux_tty_alloc_failed(struct ssh *ssh, Channel *c)
{
struct sshbuf *m;
Channel *mux_chan;
int r;
debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_S_TTY_ALLOC_FAIL)) != 0 ||
(r = sshbuf_put_u32(m, c->self)) != 0 ||
(r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
sshbuf_free(m);
}
/* Prepare a mux master to listen on a Unix domain socket. */
void
muxserver_listen(struct ssh *ssh)
{
mode_t old_umask;
char *orig_control_path = options.control_path;
char rbuf[16+1];
u_int i, r;
int oerrno;
if (options.control_path == NULL ||
options.control_master == SSHCTL_MASTER_NO)
return;
debug("setting up multiplex master socket");
/*
* Use a temporary path before listen so we can pseudo-atomically
* establish the listening socket in its final location to avoid
* other processes racing in between bind() and listen() and hitting
* an unready socket.
*/
for (i = 0; i < sizeof(rbuf) - 1; i++) {
r = arc4random_uniform(26+26+10);
rbuf[i] = (r < 26) ? 'a' + r :
(r < 26*2) ? 'A' + r - 26 :
'0' + r - 26 - 26;
}
rbuf[sizeof(rbuf) - 1] = '\0';
options.control_path = NULL;
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
debug3("%s: temporary control path %s", __func__, options.control_path);
old_umask = umask(0177);
muxserver_sock = unix_listener(options.control_path, 64, 0);
oerrno = errno;
umask(old_umask);
if (muxserver_sock < 0) {
if (oerrno == EINVAL || oerrno == EADDRINUSE) {
error("ControlSocket %s already exists, "
"disabling multiplexing", options.control_path);
disable_mux_master:
if (muxserver_sock != -1) {
close(muxserver_sock);
muxserver_sock = -1;
}
free(orig_control_path);
free(options.control_path);
options.control_path = NULL;
options.control_master = SSHCTL_MASTER_NO;
return;
} else {
/* unix_listener() logs the error */
cleanup_exit(255);
}
}
/* Now atomically "move" the mux socket into position */
if (link(options.control_path, orig_control_path) != 0) {
if (errno != EEXIST) {
fatal("%s: link mux listener %s => %s: %s", __func__,
options.control_path, orig_control_path,
strerror(errno));
}
error("ControlSocket %s already exists, disabling multiplexing",
orig_control_path);
unlink(options.control_path);
goto disable_mux_master;
}
unlink(options.control_path);
free(options.control_path);
options.control_path = orig_control_path;
set_nonblock(muxserver_sock);
mux_listener_channel = channel_new(ssh, "mux listener",
SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, options.control_path, 1);
mux_listener_channel->mux_rcb = mux_master_read_cb;
debug3("%s: mux listener channel %d fd %d", __func__,
mux_listener_channel->self, mux_listener_channel->sock);
}
/* Callback on open confirmation in mux master for a mux client session. */
static void
mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
{
struct mux_session_confirm_ctx *cctx = arg;
const char *display;
Channel *c, *cc;
int i, r;
struct sshbuf *reply;
if (cctx == NULL)
fatal("%s: cctx == NULL", __func__);
if ((c = channel_by_id(ssh, id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan);
if ((reply = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if (!success) {
debug3("%s: sending failure reply", __func__);
reply_error(reply, MUX_S_FAILURE, cctx->rid,
"Session open refused by peer");
goto done;
}
display = getenv("DISPLAY");
if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
char *proto, *data;
/* Get reasonable local authentication information. */
if (client_x11_get_proto(ssh, display, options.xauth_location,
options.forward_x11_trusted, options.forward_x11_timeout,
&proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
x11_request_forwarding_with_spoofing(ssh, id,
display, proto, data, 1);
/* XXX exit_on_forward_failure */
client_expect_confirm(ssh, id, "X11 forwarding",
CONFIRM_WARN);
}
}
if (cctx->want_agent_fwd && options.forward_agent) {
debug("Requesting authentication agent forwarding.");
channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: packet error: %s", __func__, ssh_err(r));
}
client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys,
cctx->term, &cctx->tio, c->rfd, cctx->cmd, cctx->env);
debug3("%s: sending success reply", __func__);
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
(r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
(r = sshbuf_put_u32(reply, c->self)) != 0)
fatal("%s: reply: %s", __func__, ssh_err(r));
done:
/* Send reply */
if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
sshbuf_free(reply);
if (cc->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
sshbuf_free(cctx->cmd);
free(cctx->term);
if (cctx->env != NULL) {
for (i = 0; cctx->env[i] != NULL; i++)
free(cctx->env[i]);
free(cctx->env);
}
free(cctx);
}
/* ** Multiplexing client support */
/* Exit signal handler */
static void
control_client_sighandler(int signo)
{
muxclient_terminate = signo;
}
/*
* Relay signal handler - used to pass some signals from mux client to
* mux master.
*/
static void
control_client_sigrelay(int signo)
{
int save_errno = errno;
if (muxserver_pid > 1)
kill(muxserver_pid, signo);
errno = save_errno;
}
static int
mux_client_read(int fd, struct sshbuf *b, size_t need)
{
size_t have;
ssize_t len;
u_char *p;
struct pollfd pfd;
int r;
pfd.fd = fd;
pfd.events = POLLIN;
if ((r = sshbuf_reserve(b, need, &p)) != 0)
fatal("%s: reserve: %s", __func__, ssh_err(r));
for (have = 0; have < need; ) {
if (muxclient_terminate) {
errno = EINTR;
return -1;
}
len = read(fd, p + have, need - have);
if (len < 0) {
switch (errno) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EAGAIN:
(void)poll(&pfd, 1, -1);
/* FALLTHROUGH */
case EINTR:
continue;
default:
return -1;
}
}
if (len == 0) {
errno = EPIPE;
return -1;
}
have += (size_t)len;
}
return 0;
}
static int
mux_client_write_packet(int fd, struct sshbuf *m)
{
struct sshbuf *queue;
u_int have, need;
int r, oerrno, len;
const u_char *ptr;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT;
if ((queue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_stringb(queue, m)) != 0)
fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
need = sshbuf_len(queue);
ptr = sshbuf_ptr(queue);
for (have = 0; have < need; ) {
if (muxclient_terminate) {
sshbuf_free(queue);
errno = EINTR;
return -1;
}
len = write(fd, ptr + have, need - have);
if (len < 0) {
switch (errno) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EAGAIN:
(void)poll(&pfd, 1, -1);
/* FALLTHROUGH */
case EINTR:
continue;
default:
oerrno = errno;
sshbuf_free(queue);
errno = oerrno;
return -1;
}
}
if (len == 0) {
sshbuf_free(queue);
errno = EPIPE;
return -1;
}
have += (u_int)len;
}
sshbuf_free(queue);
return 0;
}
static int
mux_client_read_packet(int fd, struct sshbuf *m)
{
struct sshbuf *queue;
size_t need, have;
const u_char *ptr;
int r, oerrno;
if ((queue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if (mux_client_read(fd, queue, 4) != 0) {
if ((oerrno = errno) == EPIPE)
debug3("%s: read header failed: %s", __func__,
strerror(errno));
sshbuf_free(queue);
errno = oerrno;
return -1;
}
need = PEEK_U32(sshbuf_ptr(queue));
if (mux_client_read(fd, queue, need) != 0) {
oerrno = errno;
debug3("%s: read body failed: %s", __func__, strerror(errno));
sshbuf_free(queue);
errno = oerrno;
return -1;
}
if ((r = sshbuf_get_string_direct(queue, &ptr, &have)) != 0 ||
(r = sshbuf_put(m, ptr, have)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(queue);
return 0;
}
static int
mux_client_hello_exchange(int fd)
{
struct sshbuf *m;
u_int type, ver;
int r, ret = -1;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 ||
(r = sshbuf_put_u32(m, SSHMUX_VER)) != 0)
fatal("%s: hello: %s", __func__, ssh_err(r));
/* no extensions */
if (mux_client_write_packet(fd, m) != 0) {
debug("%s: write packet: %s", __func__, strerror(errno));
goto out;
}
sshbuf_reset(m);
/* Read their HELLO */
if (mux_client_read_packet(fd, m) != 0) {
debug("%s: read packet failed", __func__);
goto out;
}
if ((r = sshbuf_get_u32(m, &type)) != 0)
fatal("%s: decode type: %s", __func__, ssh_err(r));
if (type != MUX_MSG_HELLO) {
error("%s: expected HELLO (%u) received %u",
__func__, MUX_MSG_HELLO, type);
goto out;
}
if ((r = sshbuf_get_u32(m, &ver)) != 0)
fatal("%s: decode version: %s", __func__, ssh_err(r));
if (ver != SSHMUX_VER) {
error("Unsupported multiplexing protocol version %d "
"(expected %d)", ver, SSHMUX_VER);
goto out;
}
debug2("%s: master version %u", __func__, ver);
/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
char *name = NULL;
if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
(r = sshbuf_skip_string(m)) != 0) { /* value */
error("%s: malformed extension: %s",
__func__, ssh_err(r));
goto out;
}
debug2("Unrecognised master extension \"%s\"", name);
free(name);
}
/* success */
ret = 0;
out:
sshbuf_free(m);
return ret;
}
static u_int
mux_client_request_alive(int fd)
{
struct sshbuf *m;
char *e;
u_int pid, type, rid;
int r;
debug3("%s: entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_C_ALIVE_CHECK)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0) {
sshbuf_free(m);
return 0;
}
if ((r = sshbuf_get_u32(m, &type)) != 0)
fatal("%s: decode type: %s", __func__, ssh_err(r));
if (type != MUX_S_ALIVE) {
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: master returned error: %s", __func__, e);
}
if ((r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode remote ID: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
if ((r = sshbuf_get_u32(m, &pid)) != 0)
fatal("%s: decode PID: %s", __func__, ssh_err(r));
sshbuf_free(m);
debug3("%s: done pid = %u", __func__, pid);
muxclient_request_id++;
return pid;
}
static void
mux_client_request_terminate(int fd)
{
struct sshbuf *m;
char *e;
u_int type, rid;
int r;
debug3("%s: entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0) {
/* Remote end exited already */
if (errno == EPIPE) {
sshbuf_free(m);
return;
}
fatal("%s: read from master failed: %s",
__func__, strerror(errno));
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("Master refused termination request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: termination request failed: %s", __func__, e);
default:
fatal("%s: unexpected response from master 0x%08x",
__func__, type);
}
sshbuf_free(m);
muxclient_request_id++;
}
static int
mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
{
struct sshbuf *m;
char *e, *fwd_desc;
const char *lhost, *chost;
u_int type, rid;
int r;
fwd_desc = format_forward(ftype, fwd);
debug("Requesting %s %s",
cancel_flag ? "cancellation of" : "forwarding of", fwd_desc);
free(fwd_desc);
type = cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD;
if (fwd->listen_path != NULL)
lhost = fwd->listen_path;
else if (fwd->listen_host == NULL)
lhost = "";
else if (*fwd->listen_host == '\0')
lhost = "*";
else
lhost = fwd->listen_host;
if (fwd->connect_path != NULL)
chost = fwd->connect_path;
else if (fwd->connect_host == NULL)
chost = "";
else
chost = fwd->connect_host;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, type)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_u32(m, ftype)) != 0 ||
(r = sshbuf_put_cstring(m, lhost)) != 0 ||
(r = sshbuf_put_u32(m, fwd->listen_port)) != 0 ||
(r = sshbuf_put_cstring(m, chost)) != 0 ||
(r = sshbuf_put_u32(m, fwd->connect_port)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0) {
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_REMOTE_PORT:
if (cancel_flag)
fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__);
if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0)
fatal("%s: decode port: %s", __func__, ssh_err(r));
verbose("Allocated port %u for remote forward to %s:%d",
fwd->allocated_port,
fwd->connect_host ? fwd->connect_host : "",
fwd->connect_port);
if (muxclient_command == SSHMUX_COMMAND_FORWARD)
fprintf(stdout, "%i\n", fwd->allocated_port);
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
sshbuf_free(m);
error("Master refused forwarding request: %s", e);
return -1;
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
sshbuf_free(m);
error("%s: forwarding request failed: %s", __func__, e);
return -1;
default:
fatal("%s: unexpected response from master 0x%08x",
__func__, type);
}
sshbuf_free(m);
muxclient_request_id++;
return 0;
}
static int
mux_client_forwards(int fd, int cancel_flag)
{
int i, ret = 0;
debug3("%s: %s forwardings: %d local, %d remote", __func__,
cancel_flag ? "cancel" : "request",
options.num_local_forwards, options.num_remote_forwards);
/* XXX ExitOnForwardingFailure */
for (i = 0; i < options.num_local_forwards; i++) {
if (mux_client_forward(fd, cancel_flag,
options.local_forwards[i].connect_port == 0 ?
MUX_FWD_DYNAMIC : MUX_FWD_LOCAL,
options.local_forwards + i) != 0)
ret = -1;
}
for (i = 0; i < options.num_remote_forwards; i++) {
if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE,
options.remote_forwards + i) != 0)
ret = -1;
}
return ret;
}
static int
mux_client_request_session(int fd)
{
struct sshbuf *m;
char *e;
const char *term;
u_int echar, rid, sid, esid, exitval, type, exitval_seen;
extern char **environ;
int r, i, devnull, rawmode;
debug3("%s: entering", __func__);
if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
error("%s: master alive request failed", __func__);
return -1;
}
signal(SIGPIPE, SIG_IGN);
if (stdin_null_flag) {
if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
fatal("open(/dev/null): %s", strerror(errno));
if (dup2(devnull, STDIN_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
if (devnull > STDERR_FILENO)
close(devnull);
}
if ((term = getenv("TERM")) == NULL)
term = "";
echar = 0xffffffff;
if (options.escape_char != SSH_ESCAPECHAR_NONE)
echar = (u_int)options.escape_char;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_C_NEW_SESSION)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_u32(m, tty_flag)) != 0 ||
(r = sshbuf_put_u32(m, options.forward_x11)) != 0 ||
(r = sshbuf_put_u32(m, options.forward_agent)) != 0 ||
(r = sshbuf_put_u32(m, subsystem_flag)) != 0 ||
(r = sshbuf_put_u32(m, echar)) != 0 ||
(r = sshbuf_put_cstring(m, term)) != 0 ||
(r = sshbuf_put_stringb(m, command)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
/* Pass environment */
if (options.num_send_env > 0 && environ != NULL) {
for (i = 0; environ[i] != NULL; i++) {
if (!env_permitted(environ[i]))
continue;
if ((r = sshbuf_put_cstring(m, environ[i])) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
}
}
for (i = 0; i < options.num_setenv; i++) {
if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
}
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
/* Send the stdio file descriptors */
if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
mm_send_fd(fd, STDOUT_FILENO) == -1 ||
mm_send_fd(fd, STDERR_FILENO) == -1)
fatal("%s: send fds failed", __func__);
debug3("%s: session request sent", __func__);
/* Read their reply */
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
error("%s: read from master failed: %s",
__func__, strerror(errno));
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
if ((r = sshbuf_get_u32(m, &sid)) != 0)
fatal("%s: decode ID: %s", __func__, ssh_err(r));
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
error("Master refused session request: %s", e);
sshbuf_free(m);
return -1;
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
error("%s: session request failed: %s", __func__, e);
sshbuf_free(m);
return -1;
default:
sshbuf_free(m);
error("%s: unexpected response from master 0x%08x",
__func__, type);
return -1;
}
muxclient_request_id++;
if (pledge("stdio proc tty", NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
platform_pledge_mux();
signal(SIGHUP, control_client_sighandler);
signal(SIGINT, control_client_sighandler);
signal(SIGTERM, control_client_sighandler);
signal(SIGWINCH, control_client_sigrelay);
rawmode = tty_flag;
if (tty_flag)
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
/*
* Stick around until the controlee closes the client_fd.
* Before it does, it is expected to write an exit message.
* This process must read the value and wait for the closure of
* the client_fd; if this one closes early, the multiplex master will
* terminate early too (possibly losing data).
*/
for (exitval = 255, exitval_seen = 0;;) {
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0)
break;
if ((r = sshbuf_get_u32(m, &type)) != 0)
fatal("%s: decode type: %s", __func__, ssh_err(r));
switch (type) {
case MUX_S_TTY_ALLOC_FAIL:
if ((r = sshbuf_get_u32(m, &esid)) != 0)
fatal("%s: decode ID: %s",
__func__, ssh_err(r));
if (esid != sid)
fatal("%s: tty alloc fail on unknown session: "
"my id %u theirs %u",
__func__, sid, esid);
leave_raw_mode(options.request_tty ==
REQUEST_TTY_FORCE);
rawmode = 0;
continue;
case MUX_S_EXIT_MESSAGE:
if ((r = sshbuf_get_u32(m, &esid)) != 0)
fatal("%s: decode ID: %s",
__func__, ssh_err(r));
if (esid != sid)
fatal("%s: exit on unknown session: "
"my id %u theirs %u",
__func__, sid, esid);
if (exitval_seen)
fatal("%s: exitval sent twice", __func__);
if ((r = sshbuf_get_u32(m, &exitval)) != 0)
fatal("%s: decode exit value: %s",
__func__, ssh_err(r));
exitval_seen = 1;
continue;
default:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s",
__func__, ssh_err(r));
fatal("%s: master returned error: %s", __func__, e);
}
}
close(fd);
if (rawmode)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
if (muxclient_terminate) {
debug2("Exiting on signal: %s", strsignal(muxclient_terminate));
exitval = 255;
} else if (!exitval_seen) {
debug2("Control master terminated unexpectedly");
exitval = 255;
} else
debug2("Received exit status from master %d", exitval);
if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
fprintf(stderr, "Shared connection to %s closed.\r\n", host);
exit(exitval);
}
static int
mux_client_proxy(int fd)
{
struct sshbuf *m;
char *e;
u_int type, rid;
int r;
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0) {
sshbuf_free(m);
return 0;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
if (type != MUX_S_PROXY) {
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: master returned error: %s", __func__, e);
}
sshbuf_free(m);
debug3("%s: done", __func__);
muxclient_request_id++;
return 0;
}
static int
mux_client_request_stdio_fwd(int fd)
{
struct sshbuf *m;
char *e;
u_int type, rid, sid;
int r, devnull;
debug3("%s: entering", __func__);
if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
error("%s: master alive request failed", __func__);
return -1;
}
signal(SIGPIPE, SIG_IGN);
if (stdin_null_flag) {
if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
fatal("open(/dev/null): %s", strerror(errno));
if (dup2(devnull, STDIN_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
if (devnull > STDERR_FILENO)
close(devnull);
}
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_C_NEW_STDIO_FWD)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_cstring(m, options.stdio_forward_host)) != 0 ||
(r = sshbuf_put_u32(m, options.stdio_forward_port)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
/* Send the stdio file descriptors */
if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
mm_send_fd(fd, STDOUT_FILENO) == -1)
fatal("%s: send fds failed", __func__);
if (pledge("stdio proc tty", NULL) == -1)
fatal("%s pledge(): %s", __func__, strerror(errno));
platform_pledge_mux();
debug3("%s: stdio forward request sent", __func__);
/* Read their reply */
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
error("%s: read from master failed: %s",
__func__, strerror(errno));
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
if ((r = sshbuf_get_u32(m, &sid)) != 0)
fatal("%s: decode ID: %s", __func__, ssh_err(r));
debug("%s: master session id: %u", __func__, sid);
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
sshbuf_free(m);
fatal("Master refused stdio forwarding request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
sshbuf_free(m);
fatal("Stdio forwarding request failed: %s", e);
default:
sshbuf_free(m);
error("%s: unexpected response from master 0x%08x",
__func__, type);
return -1;
}
muxclient_request_id++;
signal(SIGHUP, control_client_sighandler);
signal(SIGINT, control_client_sighandler);
signal(SIGTERM, control_client_sighandler);
signal(SIGWINCH, control_client_sigrelay);
/*
* Stick around until the controlee closes the client_fd.
*/
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
if (errno == EPIPE ||
(errno == EINTR && muxclient_terminate != 0))
return 0;
fatal("%s: mux_client_read_packet: %s",
__func__, strerror(errno));
}
fatal("%s: master returned unexpected message %u", __func__, type);
}
static void
mux_client_request_stop_listening(int fd)
{
struct sshbuf *m;
char *e;
u_int type, rid;
int r;
debug3("%s: entering", __func__);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if ((r = sshbuf_put_u32(m, MUX_C_STOP_LISTENING)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
fatal("%s: request: %s", __func__, ssh_err(r));
if (mux_client_write_packet(fd, m) != 0)
fatal("%s: write packet: %s", __func__, strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0)
fatal("%s: read from master failed: %s",
__func__, strerror(errno));
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
fatal("%s: decode: %s", __func__, ssh_err(r));
if (rid != muxclient_request_id)
fatal("%s: out of sequence reply: my id %u theirs %u",
__func__, muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("Master refused stop listening request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
fatal("%s: decode error: %s", __func__, ssh_err(r));
fatal("%s: stop listening request failed: %s", __func__, e);
default:
fatal("%s: unexpected response from master 0x%08x",
__func__, type);
}
sshbuf_free(m);
muxclient_request_id++;
}
/* Multiplex client main loop. */
int
muxclient(const char *path)
{
struct sockaddr_un addr;
int sock;
u_int pid;
if (muxclient_command == 0) {
if (options.stdio_forward_host != NULL)
muxclient_command = SSHMUX_COMMAND_STDIO_FWD;
else
muxclient_command = SSHMUX_COMMAND_OPEN;
}
switch (options.control_master) {
case SSHCTL_MASTER_AUTO:
case SSHCTL_MASTER_AUTO_ASK:
debug("auto-mux: Trying existing master");
/* FALLTHROUGH */
case SSHCTL_MASTER_NO:
break;
default:
return -1;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
if (strlcpy(addr.sun_path, path,
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
fatal("ControlPath too long ('%s' >= %u bytes)", path,
(unsigned int)sizeof(addr.sun_path));
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
fatal("%s socket(): %s", __func__, strerror(errno));
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
switch (muxclient_command) {
case SSHMUX_COMMAND_OPEN:
case SSHMUX_COMMAND_STDIO_FWD:
break;
default:
fatal("Control socket connect(%.100s): %s", path,
strerror(errno));
}
if (errno == ECONNREFUSED &&
options.control_master != SSHCTL_MASTER_NO) {
debug("Stale control socket %.100s, unlinking", path);
unlink(path);
} else if (errno == ENOENT) {
debug("Control socket \"%.100s\" does not exist", path);
} else {
error("Control socket connect(%.100s): %s", path,
strerror(errno));
}
close(sock);
return -1;
}
set_nonblock(sock);
if (mux_client_hello_exchange(sock) != 0) {
error("%s: master hello exchange failed", __func__);
close(sock);
return -1;
}
switch (muxclient_command) {
case SSHMUX_COMMAND_ALIVE_CHECK:
if ((pid = mux_client_request_alive(sock)) == 0)
fatal("%s: master alive check failed", __func__);
fprintf(stderr, "Master running (pid=%u)\r\n", pid);
exit(0);
case SSHMUX_COMMAND_TERMINATE:
mux_client_request_terminate(sock);
if (options.log_level != SYSLOG_LEVEL_QUIET)
fprintf(stderr, "Exit request sent.\r\n");
exit(0);
case SSHMUX_COMMAND_FORWARD:
if (mux_client_forwards(sock, 0) != 0)
fatal("%s: master forward request failed", __func__);
exit(0);
case SSHMUX_COMMAND_OPEN:
if (mux_client_forwards(sock, 0) != 0) {
error("%s: master forward request failed", __func__);
return -1;
}
mux_client_request_session(sock);
return -1;
case SSHMUX_COMMAND_STDIO_FWD:
mux_client_request_stdio_fwd(sock);
exit(0);
case SSHMUX_COMMAND_STOP:
mux_client_request_stop_listening(sock);
if (options.log_level != SYSLOG_LEVEL_QUIET)
fprintf(stderr, "Stop listening request sent.\r\n");
exit(0);
case SSHMUX_COMMAND_CANCEL_FWD:
if (mux_client_forwards(sock, 1) != 0)
error("%s: master cancel forward request failed",
__func__);
exit(0);
case SSHMUX_COMMAND_PROXY:
mux_client_proxy(sock);
return (sock);
default:
fatal("unrecognised muxclient_command %d", muxclient_command);
}
}
diff --git a/myproposal.h b/myproposal.h
index 27b4a15a1279..f16729876d99 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,209 +1,204 @@
-/* $OpenBSD: myproposal.h,v 1.57 2018/09/12 01:34:02 djm Exp $ */
+/* $OpenBSD: myproposal.h,v 1.58 2019/02/23 08:20:43 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <openssl/opensslv.h>
/* conditional algorithm support */
#ifdef OPENSSL_HAS_ECC
#ifdef OPENSSL_HAS_NISTP521
# define KEX_ECDH_METHODS \
"ecdh-sha2-nistp256," \
"ecdh-sha2-nistp384," \
"ecdh-sha2-nistp521,"
# define HOSTKEY_ECDSA_CERT_METHODS \
"ecdsa-sha2-nistp256-cert-v01@openssh.com," \
"ecdsa-sha2-nistp384-cert-v01@openssh.com," \
"ecdsa-sha2-nistp521-cert-v01@openssh.com,"
# define HOSTKEY_ECDSA_METHODS \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384," \
"ecdsa-sha2-nistp521,"
#else
# define KEX_ECDH_METHODS \
"ecdh-sha2-nistp256," \
"ecdh-sha2-nistp384,"
# define HOSTKEY_ECDSA_CERT_METHODS \
"ecdsa-sha2-nistp256-cert-v01@openssh.com," \
"ecdsa-sha2-nistp384-cert-v01@openssh.com,"
# define HOSTKEY_ECDSA_METHODS \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384,"
#endif
#else
# define KEX_ECDH_METHODS
# define HOSTKEY_ECDSA_CERT_METHODS
# define HOSTKEY_ECDSA_METHODS
#endif
#ifdef OPENSSL_HAVE_EVPGCM
# define AESGCM_CIPHER_MODES \
",aes128-gcm@openssh.com,aes256-gcm@openssh.com"
#else
# define AESGCM_CIPHER_MODES
#endif
#ifdef HAVE_EVP_SHA256
# define KEX_SHA2_METHODS \
"diffie-hellman-group-exchange-sha256," \
"diffie-hellman-group16-sha512," \
"diffie-hellman-group18-sha512,"
# define KEX_SHA2_GROUP14 \
"diffie-hellman-group14-sha256,"
#define SHA2_HMAC_MODES \
"hmac-sha2-256," \
"hmac-sha2-512,"
#else
# define KEX_SHA2_METHODS
# define KEX_SHA2_GROUP14
# define SHA2_HMAC_MODES
#endif
#ifdef WITH_OPENSSL
# ifdef HAVE_EVP_SHA256
# define KEX_CURVE25519_METHODS \
"curve25519-sha256," \
"curve25519-sha256@libssh.org,"
# else
# define KEX_CURVE25519_METHODS ""
# endif
-#define KEX_COMMON_KEX \
+#define KEX_SERVER_KEX \
KEX_CURVE25519_METHODS \
KEX_ECDH_METHODS \
- KEX_SHA2_METHODS
-
-#define KEX_SERVER_KEX KEX_COMMON_KEX \
- KEX_SHA2_GROUP14 \
- "diffie-hellman-group14-sha1" \
-
-#define KEX_CLIENT_KEX KEX_COMMON_KEX \
- "diffie-hellman-group-exchange-sha1," \
+ KEX_SHA2_METHODS \
KEX_SHA2_GROUP14 \
"diffie-hellman-group14-sha1"
+#define KEX_CLIENT_KEX KEX_SERVER_KEX
+
#define KEX_DEFAULT_PK_ALG \
HOSTKEY_ECDSA_CERT_METHODS \
"ssh-ed25519-cert-v01@openssh.com," \
"rsa-sha2-512-cert-v01@openssh.com," \
"rsa-sha2-256-cert-v01@openssh.com," \
"ssh-rsa-cert-v01@openssh.com," \
HOSTKEY_ECDSA_METHODS \
"ssh-ed25519," \
"rsa-sha2-512," \
"rsa-sha2-256," \
"ssh-rsa"
/* the actual algorithms */
#define KEX_SERVER_ENCRYPT \
"chacha20-poly1305@openssh.com," \
"aes128-ctr,aes192-ctr,aes256-ctr" \
AESGCM_CIPHER_MODES
#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT
#define KEX_SERVER_MAC \
"umac-64-etm@openssh.com," \
"umac-128-etm@openssh.com," \
"hmac-sha2-256-etm@openssh.com," \
"hmac-sha2-512-etm@openssh.com," \
"hmac-sha1-etm@openssh.com," \
"umac-64@openssh.com," \
"umac-128@openssh.com," \
"hmac-sha2-256," \
"hmac-sha2-512," \
"hmac-sha1"
#define KEX_CLIENT_MAC KEX_SERVER_MAC
/* Not a KEX value, but here so all the algorithm defaults are together */
#define SSH_ALLOWED_CA_SIGALGS \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384," \
"ecdsa-sha2-nistp521," \
"ssh-ed25519," \
"rsa-sha2-512," \
"rsa-sha2-256," \
"ssh-rsa"
#else /* WITH_OPENSSL */
#define KEX_SERVER_KEX \
"curve25519-sha256," \
"curve25519-sha256@libssh.org"
#define KEX_DEFAULT_PK_ALG \
"ssh-ed25519-cert-v01@openssh.com," \
"ssh-ed25519"
#define KEX_SERVER_ENCRYPT \
"chacha20-poly1305@openssh.com," \
"aes128-ctr,aes192-ctr,aes256-ctr"
#define KEX_SERVER_MAC \
"umac-64-etm@openssh.com," \
"umac-128-etm@openssh.com," \
"hmac-sha2-256-etm@openssh.com," \
"hmac-sha2-512-etm@openssh.com," \
"hmac-sha1-etm@openssh.com," \
"umac-64@openssh.com," \
"umac-128@openssh.com," \
"hmac-sha2-256," \
"hmac-sha2-512," \
"hmac-sha1"
#define KEX_CLIENT_KEX KEX_SERVER_KEX
#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT
#define KEX_CLIENT_MAC KEX_SERVER_MAC
#define SSH_ALLOWED_CA_SIGALGS "ssh-ed25519"
#endif /* WITH_OPENSSL */
#define KEX_DEFAULT_COMP "none,zlib@openssh.com"
#define KEX_DEFAULT_LANG ""
#define KEX_CLIENT \
KEX_CLIENT_KEX, \
KEX_DEFAULT_PK_ALG, \
KEX_CLIENT_ENCRYPT, \
KEX_CLIENT_ENCRYPT, \
KEX_CLIENT_MAC, \
KEX_CLIENT_MAC, \
KEX_DEFAULT_COMP, \
KEX_DEFAULT_COMP, \
KEX_DEFAULT_LANG, \
KEX_DEFAULT_LANG
#define KEX_SERVER \
KEX_SERVER_KEX, \
KEX_DEFAULT_PK_ALG, \
KEX_SERVER_ENCRYPT, \
KEX_SERVER_ENCRYPT, \
KEX_SERVER_MAC, \
KEX_SERVER_MAC, \
KEX_DEFAULT_COMP, \
KEX_DEFAULT_COMP, \
KEX_DEFAULT_LANG, \
KEX_DEFAULT_LANG
diff --git a/opacket.c b/opacket.c
deleted file mode 100644
index e637d7a71b5b..000000000000
--- a/opacket.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/* $OpenBSD: opacket.c,v 1.7 2017/10/20 01:56:39 djm Exp $ */
-/* Written by Markus Friedl. Placed in the public domain. */
-
-#include "includes.h"
-
-#include <stdarg.h>
-
-#include "ssherr.h"
-#include "packet.h"
-#include "log.h"
-
-struct ssh *active_state, *backup_state;
-
-/* Map old to new API */
-
-void
-ssh_packet_start(struct ssh *ssh, u_char type)
-{
- int r;
-
- if ((r = sshpkt_start(ssh, type)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_char(struct ssh *ssh, int value)
-{
- u_char ch = value;
- int r;
-
- if ((r = sshpkt_put_u8(ssh, ch)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_int(struct ssh *ssh, u_int value)
-{
- int r;
-
- if ((r = sshpkt_put_u32(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_int64(struct ssh *ssh, u_int64_t value)
-{
- int r;
-
- if ((r = sshpkt_put_u64(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_string(struct ssh *ssh, const void *buf, u_int len)
-{
- int r;
-
- if ((r = sshpkt_put_string(ssh, buf, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_cstring(struct ssh *ssh, const char *str)
-{
- int r;
-
- if ((r = sshpkt_put_cstring(ssh, str)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-void
-ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len)
-{
- int r;
-
- if ((r = sshpkt_put(ssh, buf, len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-
-#ifdef WITH_OPENSSL
-void
-ssh_packet_put_bignum2(struct ssh *ssh, BIGNUM * value)
-{
- int r;
-
- if ((r = sshpkt_put_bignum2(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-# ifdef OPENSSL_HAS_ECC
-void
-ssh_packet_put_ecpoint(struct ssh *ssh, const EC_GROUP *curve,
- const EC_POINT *point)
-{
- int r;
-
- if ((r = sshpkt_put_ec(ssh, point, curve)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-# endif
-#endif /* WITH_OPENSSL */
-
-void
-ssh_packet_send(struct ssh *ssh)
-{
- int r;
-
- if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-u_int
-ssh_packet_get_char(struct ssh *ssh)
-{
- u_char ch;
- int r;
-
- if ((r = sshpkt_get_u8(ssh, &ch)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return ch;
-}
-
-u_int
-ssh_packet_get_int(struct ssh *ssh)
-{
- u_int val;
- int r;
-
- if ((r = sshpkt_get_u32(ssh, &val)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return val;
-}
-
-u_int64_t
-ssh_packet_get_int64(struct ssh *ssh)
-{
- u_int64_t val;
- int r;
-
- if ((r = sshpkt_get_u64(ssh, &val)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- return val;
-}
-
-
-#ifdef WITH_OPENSSL
-void
-ssh_packet_get_bignum2(struct ssh *ssh, BIGNUM * value)
-{
- int r;
-
- if ((r = sshpkt_get_bignum2(ssh, value)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-
-# ifdef OPENSSL_HAS_ECC
-void
-ssh_packet_get_ecpoint(struct ssh *ssh, const EC_GROUP *curve, EC_POINT *point)
-{
- int r;
-
- if ((r = sshpkt_get_ec(ssh, point, curve)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
-}
-# endif
-#endif /* WITH_OPENSSL */
-
-void *
-ssh_packet_get_string(struct ssh *ssh, u_int *length_ptr)
-{
- int r;
- size_t len;
- u_char *val;
-
- if ((r = sshpkt_get_string(ssh, &val, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- if (length_ptr != NULL)
- *length_ptr = (u_int)len;
- return val;
-}
-
-const void *
-ssh_packet_get_string_ptr(struct ssh *ssh, u_int *length_ptr)
-{
- int r;
- size_t len;
- const u_char *val;
-
- if ((r = sshpkt_get_string_direct(ssh, &val, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- if (length_ptr != NULL)
- *length_ptr = (u_int)len;
- return val;
-}
-
-char *
-ssh_packet_get_cstring(struct ssh *ssh, u_int *length_ptr)
-{
- int r;
- size_t len;
- char *val;
-
- if ((r = sshpkt_get_cstring(ssh, &val, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
- if (length_ptr != NULL)
- *length_ptr = (u_int)len;
- return val;
-}
-
-/* Old API, that had to be reimplemented */
-
-void
-packet_set_connection(int fd_in, int fd_out)
-{
- active_state = ssh_packet_set_connection(active_state, fd_in, fd_out);
- if (active_state == NULL)
- fatal("%s: ssh_packet_set_connection failed", __func__);
-}
-
-u_int
-packet_get_char(void)
-{
- return (ssh_packet_get_char(active_state));
-}
-
-u_int
-packet_get_int(void)
-{
- return (ssh_packet_get_int(active_state));
-}
-
-int
-packet_read_seqnr(u_int32_t *seqnr)
-{
- u_char type;
- int r;
-
- if ((r = ssh_packet_read_seqnr(active_state, &type, seqnr)) != 0)
- sshpkt_fatal(active_state, __func__, r);
- return type;
-}
-
-int
-packet_read_poll_seqnr(u_int32_t *seqnr)
-{
- u_char type;
- int r;
-
- if ((r = ssh_packet_read_poll_seqnr(active_state, &type, seqnr)))
- sshpkt_fatal(active_state, __func__, r);
- return type;
-}
-
-void
-packet_close(void)
-{
- ssh_packet_close(active_state);
- active_state = NULL;
-}
-
-void
-packet_process_incoming(const char *buf, u_int len)
-{
- int r;
-
- if ((r = ssh_packet_process_incoming(active_state, buf, len)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_write_wait(void)
-{
- int r;
-
- if ((r = ssh_packet_write_wait(active_state)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_write_poll(void)
-{
- int r;
-
- if ((r = ssh_packet_write_poll(active_state)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_read_expect(int expected_type)
-{
- int r;
-
- if ((r = ssh_packet_read_expect(active_state, expected_type)) != 0)
- sshpkt_fatal(active_state, __func__, r);
-}
-
-void
-packet_disconnect(const char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- ssh_packet_disconnect(active_state, "%s", buf);
-}
-
-void
-packet_send_debug(const char *fmt, ...)
-{
- char buf[1024];
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- ssh_packet_send_debug(active_state, "%s", buf);
-}
diff --git a/opacket.h b/opacket.h
deleted file mode 100644
index f92fe586efb5..000000000000
--- a/opacket.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/* $OpenBSD: opacket.h,v 1.13 2018/07/06 09:03:02 sf Exp $ */
-#ifndef _OPACKET_H
-/* Written by Markus Friedl. Placed in the public domain. */
-
-/* Map old to new API */
-void ssh_packet_start(struct ssh *, u_char);
-void ssh_packet_put_char(struct ssh *, int ch);
-void ssh_packet_put_int(struct ssh *, u_int value);
-void ssh_packet_put_int64(struct ssh *, u_int64_t value);
-void ssh_packet_put_bignum2(struct ssh *, BIGNUM * value);
-void ssh_packet_put_ecpoint(struct ssh *, const EC_GROUP *, const EC_POINT *);
-void ssh_packet_put_string(struct ssh *, const void *buf, u_int len);
-void ssh_packet_put_cstring(struct ssh *, const char *str);
-void ssh_packet_put_raw(struct ssh *, const void *buf, u_int len);
-void ssh_packet_send(struct ssh *);
-
-u_int ssh_packet_get_char(struct ssh *);
-u_int ssh_packet_get_int(struct ssh *);
-u_int64_t ssh_packet_get_int64(struct ssh *);
-void ssh_packet_get_bignum2(struct ssh *, BIGNUM * value);
-void ssh_packet_get_ecpoint(struct ssh *, const EC_GROUP *, EC_POINT *);
-void *ssh_packet_get_string(struct ssh *, u_int *length_ptr);
-char *ssh_packet_get_cstring(struct ssh *, u_int *length_ptr);
-
-/* don't allow remaining bytes after the end of the message */
-#define ssh_packet_check_eom(ssh) \
-do { \
- int _len = ssh_packet_remaining(ssh); \
- if (_len > 0) { \
- logit("Packet integrity error (%d bytes remaining) at %s:%d", \
- _len ,__FILE__, __LINE__); \
- ssh_packet_disconnect(ssh, \
- "Packet integrity error."); \
- } \
-} while (0)
-
-/* old API */
-void packet_close(void);
-u_int packet_get_char(void);
-u_int packet_get_int(void);
-void packet_set_connection(int, int);
-int packet_read_seqnr(u_int32_t *);
-int packet_read_poll_seqnr(u_int32_t *);
-void packet_process_incoming(const char *buf, u_int len);
-void packet_write_wait(void);
-void packet_write_poll(void);
-void packet_read_expect(int expected_type);
-#define packet_set_timeout(timeout, count) \
- ssh_packet_set_timeout(active_state, (timeout), (count))
-#define packet_connection_is_on_socket() \
- ssh_packet_connection_is_on_socket(active_state)
-#define packet_set_nonblocking() \
- ssh_packet_set_nonblocking(active_state)
-#define packet_get_connection_in() \
- ssh_packet_get_connection_in(active_state)
-#define packet_get_connection_out() \
- ssh_packet_get_connection_out(active_state)
-#define packet_set_protocol_flags(protocol_flags) \
- ssh_packet_set_protocol_flags(active_state, (protocol_flags))
-#define packet_get_protocol_flags() \
- ssh_packet_get_protocol_flags(active_state)
-#define packet_start(type) \
- ssh_packet_start(active_state, (type))
-#define packet_put_char(value) \
- ssh_packet_put_char(active_state, (value))
-#define packet_put_int(value) \
- ssh_packet_put_int(active_state, (value))
-#define packet_put_int64(value) \
- ssh_packet_put_int64(active_state, (value))
-#define packet_put_string( buf, len) \
- ssh_packet_put_string(active_state, (buf), (len))
-#define packet_put_cstring(str) \
- ssh_packet_put_cstring(active_state, (str))
-#define packet_put_raw(buf, len) \
- ssh_packet_put_raw(active_state, (buf), (len))
-#define packet_put_bignum2(value) \
- ssh_packet_put_bignum2(active_state, (value))
-#define packet_send() \
- ssh_packet_send(active_state)
-#define packet_read() \
- ssh_packet_read(active_state)
-#define packet_get_int64() \
- ssh_packet_get_int64(active_state)
-#define packet_get_bignum2(value) \
- ssh_packet_get_bignum2(active_state, (value))
-#define packet_remaining() \
- ssh_packet_remaining(active_state)
-#define packet_get_string(length_ptr) \
- ssh_packet_get_string(active_state, (length_ptr))
-#define packet_get_string_ptr(length_ptr) \
- ssh_packet_get_string_ptr(active_state, (length_ptr))
-#define packet_get_cstring(length_ptr) \
- ssh_packet_get_cstring(active_state, (length_ptr))
-void packet_send_debug(const char *, ...)
- __attribute__((format(printf, 1, 2)));
-void packet_disconnect(const char *, ...)
- __attribute__((format(printf, 1, 2)))
- __attribute__((noreturn));
-#define packet_have_data_to_write() \
- ssh_packet_have_data_to_write(active_state)
-#define packet_not_very_much_data_to_write() \
- ssh_packet_not_very_much_data_to_write(active_state)
-#define packet_set_interactive(interactive, qos_interactive, qos_bulk) \
- ssh_packet_set_interactive(active_state, (interactive), (qos_interactive), (qos_bulk))
-#define packet_is_interactive() \
- ssh_packet_is_interactive(active_state)
-#define packet_set_maxsize(s) \
- ssh_packet_set_maxsize(active_state, (s))
-#define packet_inc_alive_timeouts() \
- ssh_packet_inc_alive_timeouts(active_state)
-#define packet_set_alive_timeouts(ka) \
- ssh_packet_set_alive_timeouts(active_state, (ka))
-#define packet_get_maxsize() \
- ssh_packet_get_maxsize(active_state)
-#define packet_add_padding(pad) \
- sshpkt_add_padding(active_state, (pad))
-#define packet_send_ignore(nbytes) \
- ssh_packet_send_ignore(active_state, (nbytes))
-#define packet_set_server() \
- ssh_packet_set_server(active_state)
-#define packet_set_authenticated() \
- ssh_packet_set_authenticated(active_state)
-#define packet_get_input() \
- ssh_packet_get_input(active_state)
-#define packet_get_output() \
- ssh_packet_get_output(active_state)
-#define packet_check_eom() \
- ssh_packet_check_eom(active_state)
-#define set_newkeys(mode) \
- ssh_set_newkeys(active_state, (mode))
-#define packet_get_state(m) \
- ssh_packet_get_state(active_state, m)
-#define packet_set_state(m) \
- ssh_packet_set_state(active_state, m)
-#define packet_get_raw(lenp) \
- sshpkt_ptr(active_state, lenp)
-#define packet_get_ecpoint(c,p) \
- ssh_packet_get_ecpoint(active_state, c, p)
-#define packet_put_ecpoint(c,p) \
- ssh_packet_put_ecpoint(active_state, c, p)
-#define packet_get_rekey_timeout() \
- ssh_packet_get_rekey_timeout(active_state)
-#define packet_set_rekey_limits(x,y) \
- ssh_packet_set_rekey_limits(active_state, x, y)
-#define packet_get_bytes(x,y) \
- ssh_packet_get_bytes(active_state, x, y)
-#define packet_set_mux() \
- ssh_packet_set_mux(active_state)
-#define packet_get_mux() \
- ssh_packet_get_mux(active_state)
-#define packet_clear_keys() \
- ssh_packet_clear_keys(active_state)
-
-#endif /* _OPACKET_H */
diff --git a/openbsd-compat/bsd-cygwin_util.c b/openbsd-compat/bsd-cygwin_util.c
index fb49e30f5981..54628e2607b4 100644
--- a/openbsd-compat/bsd-cygwin_util.c
+++ b/openbsd-compat/bsd-cygwin_util.c
@@ -1,120 +1,269 @@
/*
* Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Created: Sat Sep 02 12:17:00 2000 cv
*
* This file contains functions for forcing opened file descriptors to
* binary mode on Windows systems.
*/
#define NO_BINARY_OPEN /* Avoid redefining open to binary_open for this file */
#include "includes.h"
#ifdef HAVE_CYGWIN
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
#include "xmalloc.h"
int
binary_open(const char *filename, int flags, ...)
{
va_list ap;
mode_t mode;
va_start(ap, flags);
mode = va_arg(ap, mode_t);
va_end(ap);
return (open(filename, flags | O_BINARY, mode));
}
int
check_ntsec(const char *filename)
{
return (pathconf(filename, _PC_POSIX_PERMISSIONS));
}
const char *
cygwin_ssh_privsep_user()
{
static char cyg_privsep_user[DNLEN + UNLEN + 2];
if (!cyg_privsep_user[0])
{
#ifdef CW_CYGNAME_FROM_WINNAME
if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user,
sizeof cyg_privsep_user) != 0)
#endif
strlcpy(cyg_privsep_user, "sshd", sizeof(cyg_privsep_user));
}
return cyg_privsep_user;
}
#define NL(x) x, (sizeof (x) - 1)
#define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0]))
static struct wenv {
const char *name;
size_t namelen;
} wenv_arr[] = {
{ NL("ALLUSERSPROFILE=") },
{ NL("COMPUTERNAME=") },
{ NL("COMSPEC=") },
{ NL("CYGWIN=") },
{ NL("OS=") },
{ NL("PATH=") },
{ NL("PATHEXT=") },
{ NL("PROGRAMFILES=") },
{ NL("SYSTEMDRIVE=") },
{ NL("SYSTEMROOT=") },
{ NL("WINDIR=") }
};
char **
fetch_windows_environment(void)
{
char **e, **p;
unsigned int i, idx = 0;
p = xcalloc(WENV_SIZ + 1, sizeof(char *));
for (e = environ; *e != NULL; ++e) {
for (i = 0; i < WENV_SIZ; ++i) {
if (!strncmp(*e, wenv_arr[i].name, wenv_arr[i].namelen))
p[idx++] = *e;
}
}
p[idx] = NULL;
return p;
}
void
free_windows_environment(char **p)
{
free(p);
}
+/*
+ * Returns true if the given string matches the pattern (which may contain ?
+ * and * as wildcards), and zero if it does not match.
+ *
+ * The Cygwin version of this function must be case-insensitive and take
+ * Unicode characters into account.
+ */
+
+static int
+__match_pattern (const wchar_t *s, const wchar_t *pattern)
+{
+ for (;;) {
+ /* If at end of pattern, accept if also at end of string. */
+ if (!*pattern)
+ return !*s;
+
+ if (*pattern == '*') {
+ /* Skip the asterisk. */
+ pattern++;
+
+ /* If at end of pattern, accept immediately. */
+ if (!*pattern)
+ return 1;
+
+ /* If next character in pattern is known, optimize. */
+ if (*pattern != '?' && *pattern != '*') {
+ /*
+ * Look instances of the next character in
+ * pattern, and try to match starting from
+ * those.
+ */
+ for (; *s; s++)
+ if (*s == *pattern &&
+ __match_pattern(s + 1, pattern + 1))
+ return 1;
+ /* Failed. */
+ return 0;
+ }
+ /*
+ * Move ahead one character at a time and try to
+ * match at each position.
+ */
+ for (; *s; s++)
+ if (__match_pattern(s, pattern))
+ return 1;
+ /* Failed. */
+ return 0;
+ }
+ /*
+ * There must be at least one more character in the string.
+ * If we are at the end, fail.
+ */
+ if (!*s)
+ return 0;
+
+ /* Check if the next character of the string is acceptable. */
+ if (*pattern != '?' && towlower(*pattern) != towlower(*s))
+ return 0;
+
+ /* Move to the next character, both in string and in pattern. */
+ s++;
+ pattern++;
+ }
+ /* NOTREACHED */
+}
+
+static int
+_match_pattern(const char *s, const char *pattern)
+{
+ wchar_t *ws;
+ wchar_t *wpattern;
+ size_t len;
+ int ret;
+
+ if ((len = mbstowcs(NULL, s, 0)) < 0)
+ return 0;
+ ws = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t));
+ mbstowcs(ws, s, len + 1);
+ if ((len = mbstowcs(NULL, pattern, 0)) < 0)
+ return 0;
+ wpattern = (wchar_t *) xcalloc(len + 1, sizeof (wchar_t));
+ mbstowcs(wpattern, pattern, len + 1);
+ ret = __match_pattern (ws, wpattern);
+ free(ws);
+ free(wpattern);
+ return ret;
+}
+
+/*
+ * Tries to match the string against the
+ * comma-separated sequence of subpatterns (each possibly preceded by ! to
+ * indicate negation). Returns -1 if negation matches, 1 if there is
+ * a positive match, 0 if there is no match at all.
+ */
+int
+cygwin_ug_match_pattern_list(const char *string, const char *pattern)
+{
+ char sub[1024];
+ int negated;
+ int got_positive;
+ u_int i, subi, len = strlen(pattern);
+
+ got_positive = 0;
+ for (i = 0; i < len;) {
+ /* Check if the subpattern is negated. */
+ if (pattern[i] == '!') {
+ negated = 1;
+ i++;
+ } else
+ negated = 0;
+
+ /*
+ * Extract the subpattern up to a comma or end. Convert the
+ * subpattern to lowercase.
+ */
+ for (subi = 0;
+ i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
+ subi++, i++)
+ sub[subi] = pattern[i];
+ /* If subpattern too long, return failure (no match). */
+ if (subi >= sizeof(sub) - 1)
+ return 0;
+
+ /* If the subpattern was terminated by a comma, then skip it. */
+ if (i < len && pattern[i] == ',')
+ i++;
+
+ /* Null-terminate the subpattern. */
+ sub[subi] = '\0';
+
+ /* Try to match the subpattern against the string. */
+ if (_match_pattern(string, sub)) {
+ if (negated)
+ return -1; /* Negative */
+ else
+ got_positive = 1; /* Positive */
+ }
+ }
+
+ /*
+ * Return success if got a positive match. If there was a negative
+ * match, we have already returned -1 and never get here.
+ */
+ return got_positive;
+}
+
#endif /* HAVE_CYGWIN */
diff --git a/openbsd-compat/bsd-cygwin_util.h b/openbsd-compat/bsd-cygwin_util.h
index 202c055dbae7..55c5a5b81b44 100644
--- a/openbsd-compat/bsd-cygwin_util.h
+++ b/openbsd-compat/bsd-cygwin_util.h
@@ -1,65 +1,66 @@
/*
* Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Created: Sat Sep 02 12:17:00 2000 cv
*
* This file contains functions for forcing opened file descriptors to
* binary mode on Windows systems.
*/
#ifndef _BSD_CYGWIN_UTIL_H
#define _BSD_CYGWIN_UTIL_H
#ifdef HAVE_CYGWIN
#undef ERROR
/* Avoid including windows headers. */
typedef void *HANDLE;
#define INVALID_HANDLE_VALUE ((HANDLE) -1)
#define DNLEN 16
#define UNLEN 256
/* Cygwin functions for which declarations are only available when including
windows headers, so we have to define them here explicitly. */
extern HANDLE cygwin_logon_user (const struct passwd *, const char *);
extern void cygwin_set_impersonation_token (const HANDLE);
#include <sys/cygwin.h>
#include <io.h>
#define CYGWIN_SSH_PRIVSEP_USER (cygwin_ssh_privsep_user())
const char *cygwin_ssh_privsep_user();
int binary_open(const char *, int , ...);
int check_ntsec(const char *);
char **fetch_windows_environment(void);
void free_windows_environment(char **);
+int cygwin_ug_match_pattern_list(const char *, const char *);
#ifndef NO_BINARY_OPEN
#define open binary_open
#endif
#endif /* HAVE_CYGWIN */
#endif /* _BSD_CYGWIN_UTIL_H */
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c
index 5d7540a70f4b..aa1c7d7a3dd6 100644
--- a/openbsd-compat/bsd-misc.c
+++ b/openbsd-compat/bsd-misc.c
@@ -1,327 +1,428 @@
/*
* Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
+#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#ifndef HAVE___PROGNAME
char *__progname;
#endif
/*
* NB. duplicate __progname in case it is an alias for argv[0]
* Otherwise it may get clobbered by setproctitle()
*/
char *ssh_get_progname(char *argv0)
{
char *p, *q;
#ifdef HAVE___PROGNAME
extern char *__progname;
p = __progname;
#else
if (argv0 == NULL)
return ("unknown"); /* XXX */
p = strrchr(argv0, '/');
if (p == NULL)
p = argv0;
else
p++;
#endif
if ((q = strdup(p)) == NULL) {
perror("strdup");
exit(1);
}
return q;
}
#ifndef HAVE_SETLOGIN
int setlogin(const char *name)
{
return (0);
}
#endif /* !HAVE_SETLOGIN */
#ifndef HAVE_INNETGR
int innetgr(const char *netgroup, const char *host,
const char *user, const char *domain)
{
return (0);
}
#endif /* HAVE_INNETGR */
#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
int seteuid(uid_t euid)
{
return (setreuid(-1, euid));
}
#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
int setegid(uid_t egid)
{
return(setresgid(-1, egid, -1));
}
#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR)
const char *strerror(int e)
{
extern int sys_nerr;
extern char *sys_errlist[];
if ((e >= 0) && (e < sys_nerr))
return (sys_errlist[e]);
return ("unlisted error");
}
#endif
#ifndef HAVE_UTIMES
int utimes(char *filename, struct timeval *tvp)
{
struct utimbuf ub;
ub.actime = tvp[0].tv_sec;
ub.modtime = tvp[1].tv_sec;
return (utime(filename, &ub));
}
#endif
+#ifndef HAVE_UTIMENSAT
+/*
+ * A limited implementation of utimensat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+utimensat(int fd, const char *path, const struct timespec times[2],
+ int flag)
+{
+ struct timeval tv[2];
+ int ret, oflags = O_WRONLY;
+
+ tv[0].tv_sec = times[0].tv_sec;
+ tv[0].tv_usec = times[0].tv_nsec / 1000;
+ tv[1].tv_sec = times[1].tv_sec;
+ tv[1].tv_usec = times[1].tv_nsec / 1000;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FUTIMES
+ return utimes(path, tv);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = futimes(fd, tv);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
+#ifndef HAVE_FCHOWNAT
+/*
+ * A limited implementation of fchownat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag)
+{
+ int ret, oflags = O_WRONLY;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FCHOWN
+ return chown(pathname, owner, group);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = fchown(fd, owner, group);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
+#ifndef HAVE_FCHMODAT
+/*
+ * A limited implementation of fchmodat() that only implements the
+ * functionality used by OpenSSH, currently only AT_FDCWD and
+ * AT_SYMLINK_NOFOLLOW.
+ */
+int
+fchmodat(int fd, const char *path, mode_t mode, int flag)
+{
+ int ret, oflags = O_WRONLY;
+
+ if (fd != AT_FDCWD) {
+ errno = ENOSYS;
+ return -1;
+ }
+# ifndef HAVE_FCHMOD
+ return chown(pathname, owner, group);
+# else
+# ifdef O_NOFOLLOW
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ oflags |= O_NOFOLLOW;
+# endif /* O_NOFOLLOW */
+ if ((fd = open(path, oflags)) == -1)
+ return -1;
+ ret = fchmod(fd, mode);
+ close(fd);
+ return ret;
+# endif
+}
+#endif
+
#ifndef HAVE_TRUNCATE
int truncate(const char *path, off_t length)
{
int fd, ret, saverrno;
fd = open(path, O_WRONLY);
if (fd < 0)
return (-1);
ret = ftruncate(fd, length);
saverrno = errno;
close(fd);
if (ret == -1)
errno = saverrno;
return(ret);
}
#endif /* HAVE_TRUNCATE */
#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
int nanosleep(const struct timespec *req, struct timespec *rem)
{
int rc, saverrno;
extern int errno;
struct timeval tstart, tstop, tremain, time2wait;
TIMESPEC_TO_TIMEVAL(&time2wait, req)
(void) gettimeofday(&tstart, NULL);
rc = select(0, NULL, NULL, NULL, &time2wait);
if (rc == -1) {
saverrno = errno;
(void) gettimeofday (&tstop, NULL);
errno = saverrno;
tremain.tv_sec = time2wait.tv_sec -
(tstop.tv_sec - tstart.tv_sec);
tremain.tv_usec = time2wait.tv_usec -
(tstop.tv_usec - tstart.tv_usec);
tremain.tv_sec += tremain.tv_usec / 1000000L;
tremain.tv_usec %= 1000000L;
} else {
tremain.tv_sec = 0;
tremain.tv_usec = 0;
}
if (rem != NULL)
TIMEVAL_TO_TIMESPEC(&tremain, rem)
return(rc);
}
#endif
#if !defined(HAVE_USLEEP)
int usleep(unsigned int useconds)
{
struct timespec ts;
ts.tv_sec = useconds / 1000000;
ts.tv_nsec = (useconds % 1000000) * 1000;
return nanosleep(&ts, NULL);
}
#endif
#ifndef HAVE_TCGETPGRP
pid_t
tcgetpgrp(int fd)
{
int ctty_pgrp;
if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1)
return(-1);
else
return(ctty_pgrp);
}
#endif /* HAVE_TCGETPGRP */
#ifndef HAVE_TCSENDBREAK
int
tcsendbreak(int fd, int duration)
{
# if defined(TIOCSBRK) && defined(TIOCCBRK)
struct timeval sleepytime;
sleepytime.tv_sec = 0;
sleepytime.tv_usec = 400000;
if (ioctl(fd, TIOCSBRK, 0) == -1)
return (-1);
(void)select(0, 0, 0, 0, &sleepytime);
if (ioctl(fd, TIOCCBRK, 0) == -1)
return (-1);
return (0);
# else
return -1;
# endif
}
#endif /* HAVE_TCSENDBREAK */
#ifndef HAVE_STRDUP
char *
strdup(const char *str)
{
size_t len;
char *cp;
len = strlen(str) + 1;
cp = malloc(len);
if (cp != NULL)
return(memcpy(cp, str, len));
return NULL;
}
#endif
#ifndef HAVE_ISBLANK
int
isblank(int c)
{
return (c == ' ' || c == '\t');
}
#endif
#ifndef HAVE_GETPGID
pid_t
getpgid(pid_t pid)
{
#if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) && GETPGRP_VOID == 0
return getpgrp(pid);
#elif defined(HAVE_GETPGRP)
if (pid == 0)
return getpgrp();
#endif
errno = ESRCH;
return -1;
}
#endif
#ifndef HAVE_PLEDGE
int
pledge(const char *promises, const char *paths[])
{
return 0;
}
#endif
#ifndef HAVE_MBTOWC
/* a mbtowc that only supports ASCII */
int
mbtowc(wchar_t *pwc, const char *s, size_t n)
{
if (s == NULL || *s == '\0')
return 0; /* ASCII is not state-dependent */
if (*s < 0 || *s > 0x7f || n < 1) {
errno = EOPNOTSUPP;
return -1;
}
if (pwc != NULL)
*pwc = *s;
return 1;
}
#endif
#ifndef HAVE_LLABS
long long
llabs(long long j)
{
return (j < 0 ? -j : j);
}
#endif
#ifndef HAVE_BZERO
void
bzero(void *b, size_t n)
{
(void)memset(b, 0, n);
}
#endif
#ifndef HAVE_RAISE
int
raise(int sig)
{
kill(getpid(), sig);
}
#endif
#ifndef HAVE_GETSID
pid_t
getsid(pid_t pid)
{
errno = ENOSYS;
return -1;
}
#endif
#ifdef FFLUSH_NULL_BUG
#undef fflush
int _ssh_compat_fflush(FILE *f)
{
int r1, r2;
if (f == NULL) {
r1 = fflush(stdout);
r2 = fflush(stderr);
if (r1 == -1 || r2 == -1)
return -1;
return 0;
}
return fflush(f);
}
#endif
diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h
index 52ec528538b5..cb158cd5c16b 100644
--- a/openbsd-compat/bsd-misc.h
+++ b/openbsd-compat/bsd-misc.h
@@ -1,160 +1,180 @@
/*
* Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BSD_MISC_H
#define _BSD_MISC_H
#include "includes.h"
char *ssh_get_progname(char *);
#ifndef HAVE_SETSID
#define setsid() setpgrp(0, getpid())
#endif /* !HAVE_SETSID */
#ifndef HAVE_SETENV
int setenv(const char *, const char *, int);
#endif /* !HAVE_SETENV */
#ifndef HAVE_SETLOGIN
int setlogin(const char *);
#endif /* !HAVE_SETLOGIN */
#ifndef HAVE_INNETGR
int innetgr(const char *, const char *, const char *, const char *);
#endif /* HAVE_INNETGR */
#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
int seteuid(uid_t);
#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
int setegid(uid_t);
#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR)
const char *strerror(int);
#endif
#if !defined(HAVE_SETLINEBUF)
#define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0))
#endif
#ifndef HAVE_UTIMES
#ifndef HAVE_STRUCT_TIMEVAL
struct timeval {
long tv_sec;
long tv_usec;
}
#endif /* HAVE_STRUCT_TIMEVAL */
int utimes(char *, struct timeval *);
#endif /* HAVE_UTIMES */
+#ifndef HAVE_UTIMENSAT
+/* start with the high bits and work down to minimise risk of overlap */
+# ifndef AT_SYMLINK_NOFOLLOW
+# define AT_SYMLINK_NOFOLLOW 0x80000000
+# endif
+int utimensat(int, const char *, const struct timespec[2], int);
+#endif
+
+#ifndef AT_FDCWD
+# define AT_FDCWD (-2)
+#endif
+
+#ifndef HAVE_FCHMODAT
+int fchmodat(int, const char *, mode_t, int);
+#endif
+
+#ifndef HAVE_FCHOWNAT
+int fchownat(int, const char *, uid_t, gid_t, int);
+#endif
+
#ifndef HAVE_TRUNCATE
int truncate (const char *, off_t);
#endif /* HAVE_TRUNCATE */
#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
#ifndef HAVE_STRUCT_TIMESPEC
struct timespec {
time_t tv_sec;
long tv_nsec;
};
#endif
int nanosleep(const struct timespec *, struct timespec *);
#endif
#ifndef HAVE_USLEEP
int usleep(unsigned int useconds);
#endif
#ifndef HAVE_TCGETPGRP
pid_t tcgetpgrp(int);
#endif
#ifndef HAVE_TCSENDBREAK
int tcsendbreak(int, int);
#endif
#ifndef HAVE_UNSETENV
int unsetenv(const char *);
#endif
#ifndef HAVE_ISBLANK
int isblank(int);
#endif
#ifndef HAVE_GETPGID
pid_t getpgid(pid_t);
#endif
#ifndef HAVE_ENDGRENT
# define endgrent() do { } while(0)
#endif
#ifndef HAVE_KRB5_GET_ERROR_MESSAGE
# define krb5_get_error_message krb5_get_err_text
#endif
#ifndef HAVE_KRB5_FREE_ERROR_MESSAGE
# define krb5_free_error_message(a,b) do { } while(0)
#endif
#ifndef HAVE_PLEDGE
int pledge(const char *promises, const char *paths[]);
#endif
/* bsd-err.h */
#ifndef HAVE_ERR
void err(int, const char *, ...) __attribute__((format(printf, 2, 3)));
#endif
#ifndef HAVE_ERRX
void errx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
#endif
#ifndef HAVE_WARN
void warn(const char *, ...) __attribute__((format(printf, 1, 2)));
#endif
#ifndef HAVE_LLABS
long long llabs(long long);
#endif
#if defined(HAVE_DECL_BZERO) && HAVE_DECL_BZERO == 0
void bzero(void *, size_t);
#endif
#ifndef HAVE_RAISE
int raise(int);
#endif
#ifndef HAVE_GETSID
pid_t getsid(pid_t);
#endif
#ifndef HAVE_FLOCK
# define LOCK_SH 0x01
# define LOCK_EX 0x02
# define LOCK_NB 0x04
# define LOCK_UN 0x08
int flock(int, int);
#endif
#ifdef FFLUSH_NULL_BUG
# define fflush(x) (_ssh_compat_fflush(x))
#endif
#endif /* _BSD_MISC_H */
diff --git a/openbsd-compat/libressl-api-compat.c b/openbsd-compat/libressl-api-compat.c
index de3e64a63f12..ae00ff593b7e 100644
--- a/openbsd-compat/libressl-api-compat.c
+++ b/openbsd-compat/libressl-api-compat.c
@@ -1,636 +1,640 @@
/* $OpenBSD: dsa_lib.c,v 1.29 2018/04/14 07:09:21 tb Exp $ */
/* $OpenBSD: rsa_lib.c,v 1.37 2018/04/14 07:09:21 tb Exp $ */
/* $OpenBSD: evp_lib.c,v 1.17 2018/09/12 06:35:38 djm Exp $ */
/* $OpenBSD: dh_lib.c,v 1.32 2018/05/02 15:48:38 tb Exp $ */
/* $OpenBSD: p_lib.c,v 1.24 2018/05/30 15:40:50 tb Exp $ */
/* $OpenBSD: digest.c,v 1.30 2018/04/14 07:09:21 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* $OpenBSD: dsa_asn1.c,v 1.22 2018/06/14 17:03:19 jsing Exp $ */
/* $OpenBSD: ecs_asn1.c,v 1.9 2018/03/17 15:24:44 tb Exp $ */
/* $OpenBSD: digest.c,v 1.30 2018/04/14 07:09:21 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* $OpenBSD: rsa_meth.c,v 1.2 2018/09/12 06:35:38 djm Exp $ */
/*
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef WITH_OPENSSL
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
+#ifdef OPENSSL_HAS_ECC
#include <openssl/ecdsa.h>
+#endif
#include <openssl/dh.h>
#ifndef HAVE_DSA_GET0_PQG
void
DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
if (p != NULL)
*p = d->p;
if (q != NULL)
*q = d->q;
if (g != NULL)
*g = d->g;
}
#endif /* HAVE_DSA_GET0_PQG */
#ifndef HAVE_DSA_SET0_PQG
int
DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) ||
(d->g == NULL && g == NULL))
return 0;
if (p != NULL) {
BN_free(d->p);
d->p = p;
}
if (q != NULL) {
BN_free(d->q);
d->q = q;
}
if (g != NULL) {
BN_free(d->g);
d->g = g;
}
return 1;
}
#endif /* HAVE_DSA_SET0_PQG */
#ifndef HAVE_DSA_GET0_KEY
void
DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
{
if (pub_key != NULL)
*pub_key = d->pub_key;
if (priv_key != NULL)
*priv_key = d->priv_key;
}
#endif /* HAVE_DSA_GET0_KEY */
#ifndef HAVE_DSA_SET0_KEY
int
DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
{
if (d->pub_key == NULL && pub_key == NULL)
return 0;
if (pub_key != NULL) {
BN_free(d->pub_key);
d->pub_key = pub_key;
}
if (priv_key != NULL) {
BN_free(d->priv_key);
d->priv_key = priv_key;
}
return 1;
}
#endif /* HAVE_DSA_SET0_KEY */
#ifndef HAVE_RSA_GET0_KEY
void
RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{
if (n != NULL)
*n = r->n;
if (e != NULL)
*e = r->e;
if (d != NULL)
*d = r->d;
}
#endif /* HAVE_RSA_GET0_KEY */
#ifndef HAVE_RSA_SET0_KEY
int
RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
{
if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL))
return 0;
if (n != NULL) {
BN_free(r->n);
r->n = n;
}
if (e != NULL) {
BN_free(r->e);
r->e = e;
}
if (d != NULL) {
BN_free(r->d);
r->d = d;
}
return 1;
}
#endif /* HAVE_RSA_SET0_KEY */
#ifndef HAVE_RSA_GET0_CRT_PARAMS
void
RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp)
{
if (dmp1 != NULL)
*dmp1 = r->dmp1;
if (dmq1 != NULL)
*dmq1 = r->dmq1;
if (iqmp != NULL)
*iqmp = r->iqmp;
}
#endif /* HAVE_RSA_GET0_CRT_PARAMS */
#ifndef HAVE_RSA_SET0_CRT_PARAMS
int
RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
{
if ((r->dmp1 == NULL && dmp1 == NULL) ||
(r->dmq1 == NULL && dmq1 == NULL) ||
(r->iqmp == NULL && iqmp == NULL))
return 0;
if (dmp1 != NULL) {
BN_free(r->dmp1);
r->dmp1 = dmp1;
}
if (dmq1 != NULL) {
BN_free(r->dmq1);
r->dmq1 = dmq1;
}
if (iqmp != NULL) {
BN_free(r->iqmp);
r->iqmp = iqmp;
}
return 1;
}
#endif /* HAVE_RSA_SET0_CRT_PARAMS */
#ifndef HAVE_RSA_GET0_FACTORS
void
RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
{
if (p != NULL)
*p = r->p;
if (q != NULL)
*q = r->q;
}
#endif /* HAVE_RSA_GET0_FACTORS */
#ifndef HAVE_RSA_SET0_FACTORS
int
RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
{
if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL))
return 0;
if (p != NULL) {
BN_free(r->p);
r->p = p;
}
if (q != NULL) {
BN_free(r->q);
r->q = q;
}
return 1;
}
#endif /* HAVE_RSA_SET0_FACTORS */
#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
int
EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
{
if (ctx == NULL)
return 0;
if (EVP_CIPHER_CTX_iv_length(ctx) < 0)
return 0;
if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx))
return 0;
if (len > EVP_MAX_IV_LENGTH)
return 0; /* sanity check; shouldn't happen */
/*
* Skip the memcpy entirely when the requested IV length is zero,
* since the iv pointer may be NULL or invalid.
*/
if (len != 0) {
if (iv == NULL)
return 0;
# ifdef HAVE_EVP_CIPHER_CTX_IV
memcpy(iv, EVP_CIPHER_CTX_iv(ctx), len);
# else
memcpy(iv, ctx->iv, len);
# endif /* HAVE_EVP_CIPHER_CTX_IV */
}
return 1;
}
#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
#ifndef HAVE_EVP_CIPHER_CTX_SET_IV
int
EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, const unsigned char *iv, size_t len)
{
if (ctx == NULL)
return 0;
if (EVP_CIPHER_CTX_iv_length(ctx) < 0)
return 0;
if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx))
return 0;
if (len > EVP_MAX_IV_LENGTH)
return 0; /* sanity check; shouldn't happen */
/*
* Skip the memcpy entirely when the requested IV length is zero,
* since the iv pointer may be NULL or invalid.
*/
if (len != 0) {
if (iv == NULL)
return 0;
# ifdef HAVE_EVP_CIPHER_CTX_IV_NOCONST
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, len);
# else
memcpy(ctx->iv, iv, len);
# endif /* HAVE_EVP_CIPHER_CTX_IV_NOCONST */
}
return 1;
}
#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */
#ifndef HAVE_DSA_SIG_GET0
void
DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
#endif /* HAVE_DSA_SIG_GET0 */
#ifndef HAVE_DSA_SIG_SET0
int
DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
sig->r = r;
BN_clear_free(sig->s);
sig->s = s;
return 1;
}
#endif /* HAVE_DSA_SIG_SET0 */
+#ifdef OPENSSL_HAS_ECC
#ifndef HAVE_ECDSA_SIG_GET0
void
ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
if (ps != NULL)
*ps = sig->s;
}
#endif /* HAVE_ECDSA_SIG_GET0 */
#ifndef HAVE_ECDSA_SIG_SET0
int
ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
if (r == NULL || s == NULL)
return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
sig->s = s;
return 1;
}
#endif /* HAVE_ECDSA_SIG_SET0 */
+#endif /* OPENSSL_HAS_ECC */
#ifndef HAVE_DH_GET0_PQG
void
DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
{
if (p != NULL)
*p = dh->p;
if (q != NULL)
*q = dh->q;
if (g != NULL)
*g = dh->g;
}
#endif /* HAVE_DH_GET0_PQG */
#ifndef HAVE_DH_SET0_PQG
int
DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{
if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL))
return 0;
if (p != NULL) {
BN_free(dh->p);
dh->p = p;
}
if (q != NULL) {
BN_free(dh->q);
dh->q = q;
}
if (g != NULL) {
BN_free(dh->g);
dh->g = g;
}
return 1;
}
#endif /* HAVE_DH_SET0_PQG */
#ifndef HAVE_DH_GET0_KEY
void
DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
{
if (pub_key != NULL)
*pub_key = dh->pub_key;
if (priv_key != NULL)
*priv_key = dh->priv_key;
}
#endif /* HAVE_DH_GET0_KEY */
#ifndef HAVE_DH_SET0_KEY
int
DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
{
if (pub_key != NULL) {
BN_free(dh->pub_key);
dh->pub_key = pub_key;
}
if (priv_key != NULL) {
BN_free(dh->priv_key);
dh->priv_key = priv_key;
}
return 1;
}
#endif /* HAVE_DH_SET0_KEY */
#ifndef HAVE_DH_SET_LENGTH
int
DH_set_length(DH *dh, long length)
{
if (length < 0 || length > INT_MAX)
return 0;
dh->length = length;
return 1;
}
#endif /* HAVE_DH_SET_LENGTH */
#ifndef HAVE_RSA_METH_FREE
void
RSA_meth_free(RSA_METHOD *meth)
{
if (meth != NULL) {
free((char *)meth->name);
free(meth);
}
}
#endif /* HAVE_RSA_METH_FREE */
#ifndef HAVE_RSA_METH_DUP
RSA_METHOD *
RSA_meth_dup(const RSA_METHOD *meth)
{
RSA_METHOD *copy;
if ((copy = calloc(1, sizeof(*copy))) == NULL)
return NULL;
memcpy(copy, meth, sizeof(*copy));
if ((copy->name = strdup(meth->name)) == NULL) {
free(copy);
return NULL;
}
return copy;
}
#endif /* HAVE_RSA_METH_DUP */
#ifndef HAVE_RSA_METH_SET1_NAME
int
RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
{
char *copy;
if ((copy = strdup(name)) == NULL)
return 0;
free((char *)meth->name);
meth->name = copy;
return 1;
}
#endif /* HAVE_RSA_METH_SET1_NAME */
#ifndef HAVE_RSA_METH_GET_FINISH
int
(*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa)
{
return meth->finish;
}
#endif /* HAVE_RSA_METH_GET_FINISH */
#ifndef HAVE_RSA_METH_SET_PRIV_ENC
int
RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen,
const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
{
meth->rsa_priv_enc = priv_enc;
return 1;
}
#endif /* HAVE_RSA_METH_SET_PRIV_ENC */
#ifndef HAVE_RSA_METH_SET_PRIV_DEC
int
RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen,
const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
{
meth->rsa_priv_dec = priv_dec;
return 1;
}
#endif /* HAVE_RSA_METH_SET_PRIV_DEC */
#ifndef HAVE_RSA_METH_SET_FINISH
int
RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa))
{
meth->finish = finish;
return 1;
}
#endif /* HAVE_RSA_METH_SET_FINISH */
#ifndef HAVE_EVP_PKEY_GET0_RSA
RSA *
EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_RSA) {
/* EVPerror(EVP_R_EXPECTING_AN_RSA_KEY); */
return NULL;
}
return pkey->pkey.rsa;
}
#endif /* HAVE_EVP_PKEY_GET0_RSA */
#ifndef HAVE_EVP_MD_CTX_NEW
EVP_MD_CTX *
EVP_MD_CTX_new(void)
{
return calloc(1, sizeof(EVP_MD_CTX));
}
#endif /* HAVE_EVP_MD_CTX_NEW */
#ifndef HAVE_EVP_MD_CTX_FREE
void
EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
if (ctx == NULL)
return;
EVP_MD_CTX_cleanup(ctx);
free(ctx);
}
#endif /* HAVE_EVP_MD_CTX_FREE */
#endif /* WITH_OPENSSL */
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h
index f5c833bf271f..865aaee532bd 100644
--- a/openbsd-compat/openbsd-compat.h
+++ b/openbsd-compat/openbsd-compat.h
@@ -1,356 +1,357 @@
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
* Copyright (c) 2003 Ben Lindstrom. All rights reserved.
* Copyright (c) 2002 Tim Rice. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _OPENBSD_COMPAT_H
#define _OPENBSD_COMPAT_H
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <sys/socket.h>
#include <stddef.h> /* for wchar_t */
/* OpenBSD function replacements */
#include "base64.h"
#include "sigact.h"
#include "readpassphrase.h"
#include "vis.h"
#include "getrrsetbyname.h"
#include "sha1.h"
#include "sha2.h"
#include "rmd160.h"
#include "md5.h"
#include "blf.h"
#ifndef HAVE_BASENAME
char *basename(const char *path);
#endif
#ifndef HAVE_BINDRESVPORT_SA
int bindresvport_sa(int sd, struct sockaddr *sa);
#endif
#ifndef HAVE_CLOSEFROM
void closefrom(int);
#endif
#ifndef HAVE_GETLINE
+#include <stdio.h>
ssize_t getline(char **, size_t *, FILE *);
#endif
#ifndef HAVE_GETPAGESIZE
int getpagesize(void);
#endif
#ifndef HAVE_GETCWD
char *getcwd(char *pt, size_t size);
#endif
#ifndef HAVE_REALLOCARRAY
void *reallocarray(void *, size_t, size_t);
#endif
#ifndef HAVE_RECALLOCARRAY
void *recallocarray(void *, size_t, size_t, size_t);
#endif
#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)
/*
* glibc's FORTIFY_SOURCE can redefine this and prevent us picking up the
* compat version.
*/
# ifdef BROKEN_REALPATH
# define realpath(x, y) _ssh_compat_realpath(x, y)
# endif
char *realpath(const char *path, char *resolved);
#endif
#ifndef HAVE_RRESVPORT_AF
int rresvport_af(int *alport, sa_family_t af);
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#ifndef HAVE_STRCASESTR
char *strcasestr(const char *, const char *);
#endif
#ifndef HAVE_SETENV
int setenv(register const char *name, register const char *value, int rewrite);
#endif
#ifndef HAVE_STRMODE
void strmode(int mode, char *p);
#endif
#ifndef HAVE_STRPTIME
#include <time.h>
char *strptime(const char *buf, const char *fmt, struct tm *tm);
#endif
#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
int mkstemps(char *path, int slen);
int mkstemp(char *path);
char *mkdtemp(char *path);
#endif
#ifndef HAVE_DAEMON
int daemon(int nochdir, int noclose);
#endif
#ifndef HAVE_DIRNAME
char *dirname(const char *path);
#endif
#ifndef HAVE_FMT_SCALED
#define FMT_SCALED_STRSIZE 7
int fmt_scaled(long long number, char *result);
#endif
#ifndef HAVE_SCAN_SCALED
int scan_scaled(char *, long long *);
#endif
#if defined(BROKEN_INET_NTOA) || !defined(HAVE_INET_NTOA)
char *inet_ntoa(struct in_addr in);
#endif
#ifndef HAVE_INET_NTOP
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
#endif
#ifndef HAVE_INET_ATON
int inet_aton(const char *cp, struct in_addr *addr);
#endif
#ifndef HAVE_STRSEP
char *strsep(char **stringp, const char *delim);
#endif
#ifndef HAVE_SETPROCTITLE
void setproctitle(const char *fmt, ...);
void compat_init_setproctitle(int argc, char *argv[]);
#endif
#ifndef HAVE_GETGROUPLIST
int getgrouplist(const char *, gid_t, gid_t *, int *);
#endif
#if !defined(HAVE_GETOPT) || !defined(HAVE_GETOPT_OPTRESET)
int BSDgetopt(int argc, char * const *argv, const char *opts);
#include "openbsd-compat/getopt.h"
#endif
#if ((defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0) || \
(defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0))
# include <sys/types.h>
# include <sys/uio.h>
# if defined(HAVE_DECL_READV) && HAVE_DECL_READV == 0
int readv(int, struct iovec *, int);
# endif
# if defined(HAVE_DECL_WRITEV) && HAVE_DECL_WRITEV == 0
int writev(int, struct iovec *, int);
# endif
#endif
/* Home grown routines */
#include "bsd-misc.h"
#include "bsd-setres_id.h"
#include "bsd-signal.h"
#include "bsd-statvfs.h"
#include "bsd-waitpid.h"
#include "bsd-poll.h"
#ifndef HAVE_GETPEEREID
int getpeereid(int , uid_t *, gid_t *);
#endif
#ifdef HAVE_ARC4RANDOM
# ifndef HAVE_ARC4RANDOM_STIR
# define arc4random_stir()
# endif
#else
unsigned int arc4random(void);
void arc4random_stir(void);
#endif /* !HAVE_ARC4RANDOM */
#ifndef HAVE_ARC4RANDOM_BUF
void arc4random_buf(void *, size_t);
#endif
#ifndef HAVE_ARC4RANDOM_UNIFORM
u_int32_t arc4random_uniform(u_int32_t);
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **, const char *, ...);
#endif
#ifndef HAVE_OPENPTY
# include <sys/ioctl.h> /* for struct winsize */
int openpty(int *, int *, char *, struct termios *, struct winsize *);
#endif /* HAVE_OPENPTY */
#ifndef HAVE_SNPRINTF
int snprintf(char *, size_t, SNPRINTF_CONST char *, ...);
#endif
#ifndef HAVE_STRTOLL
long long strtoll(const char *, char **, int);
#endif
#ifndef HAVE_STRTOUL
unsigned long strtoul(const char *, char **, int);
#endif
#ifndef HAVE_STRTOULL
unsigned long long strtoull(const char *, char **, int);
#endif
#ifndef HAVE_STRTONUM
long long strtonum(const char *, long long, long long, const char **);
#endif
/* multibyte character support */
#ifndef HAVE_MBLEN
# define mblen(x, y) (1)
#endif
#ifndef HAVE_WCWIDTH
# define wcwidth(x) (((x) >= 0x20 && (x) <= 0x7e) ? 1 : -1)
/* force our no-op nl_langinfo and mbtowc */
# undef HAVE_NL_LANGINFO
# undef HAVE_MBTOWC
# undef HAVE_LANGINFO_H
#endif
#ifndef HAVE_NL_LANGINFO
# define nl_langinfo(x) ""
#endif
#ifndef HAVE_MBTOWC
int mbtowc(wchar_t *, const char*, size_t);
#endif
#if !defined(HAVE_VASPRINTF) || !defined(HAVE_VSNPRINTF)
# include <stdarg.h>
#endif
/*
* Some platforms unconditionally undefine va_copy() so we define VA_COPY()
* instead. This is known to be the case on at least some configurations of
* AIX with the xlc compiler.
*/
#ifndef VA_COPY
# ifdef HAVE_VA_COPY
# define VA_COPY(dest, src) va_copy(dest, src)
# else
# ifdef HAVE___VA_COPY
# define VA_COPY(dest, src) __va_copy(dest, src)
# else
# define VA_COPY(dest, src) (dest) = (src)
# endif
# endif
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **, const char *, va_list);
#endif
#ifndef HAVE_VSNPRINTF
int vsnprintf(char *, size_t, const char *, va_list);
#endif
#ifndef HAVE_USER_FROM_UID
char *user_from_uid(uid_t, int);
#endif
#ifndef HAVE_GROUP_FROM_GID
char *group_from_gid(gid_t, int);
#endif
#ifndef HAVE_TIMINGSAFE_BCMP
int timingsafe_bcmp(const void *, const void *, size_t);
#endif
#ifndef HAVE_BCRYPT_PBKDF
int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t,
u_int8_t *, size_t, unsigned int);
#endif
#ifndef HAVE_EXPLICIT_BZERO
void explicit_bzero(void *p, size_t n);
#endif
#ifndef HAVE_FREEZERO
void freezero(void *, size_t);
#endif
char *xcrypt(const char *password, const char *salt);
char *shadow_pw(struct passwd *pw);
/* rfc2553 socket API replacements */
#include "fake-rfc2553.h"
/* Routines for a single OS platform */
#include "bsd-cygwin_util.h"
#include "port-aix.h"
#include "port-irix.h"
#include "port-linux.h"
#include "port-solaris.h"
#include "port-net.h"
#include "port-uw.h"
/* _FORTIFY_SOURCE breaks FD_ISSET(n)/FD_SET(n) for n > FD_SETSIZE. Avoid. */
#if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE)
# include <features.h>
# if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0)
# include <sys/socket.h> /* Ensure include guard is defined */
# undef FD_SET
# undef FD_ISSET
# define FD_SET(n, set) kludge_FD_SET(n, set)
# define FD_ISSET(n, set) kludge_FD_ISSET(n, set)
void kludge_FD_SET(int, fd_set *);
int kludge_FD_ISSET(int, fd_set *);
# endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */
# endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */
#endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */
#endif /* _OPENBSD_COMPAT_H */
diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
index 8b4a36274606..a37ca61bf2d4 100644
--- a/openbsd-compat/openssl-compat.c
+++ b/openbsd-compat/openssl-compat.c
@@ -1,88 +1,96 @@
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS
#include "includes.h"
#ifdef WITH_OPENSSL
#include <stdarg.h>
#include <string.h>
#ifdef USE_OPENSSL_ENGINE
# include <openssl/engine.h>
# include <openssl/conf.h>
#endif
#include "log.h"
#include "openssl-compat.h"
/*
* OpenSSL version numbers: MNNFFPPS: major minor fix patch status
* We match major, minor, fix and status (not patch) for <1.0.0.
* After that, we acceptable compatible fix versions (so we
* allow 1.0.1 to work with 1.0.0). Going backwards is only allowed
* within a patch series.
*/
int
ssh_compatible_openssl(long headerver, long libver)
{
long mask, hfix, lfix;
/* exact match is always OK */
if (headerver == libver)
return 1;
/* for versions < 1.0.0, major,minor,fix,status must match */
if (headerver < 0x1000000f) {
mask = 0xfffff00fL; /* major,minor,fix,status */
return (headerver & mask) == (libver & mask);
}
/*
* For versions >= 1.0.0, major,minor,status must match and library
* fix version must be equal to or newer than the header.
*/
mask = 0xfff0000fL; /* major,minor,status */
hfix = (headerver & 0x000ff000) >> 12;
lfix = (libver & 0x000ff000) >> 12;
if ( (headerver & mask) == (libver & mask) && lfix >= hfix)
return 1;
return 0;
}
-#ifdef USE_OPENSSL_ENGINE
void
-ssh_OpenSSL_add_all_algorithms(void)
+ssh_libcrypto_init(void)
{
+#if defined(HAVE_OPENSSL_INIT_CRYPTO) && \
+ defined(OPENSSL_INIT_ADD_ALL_CIPHERS) && \
+ defined(OPENSSL_INIT_ADD_ALL_DIGESTS)
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
+ OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
+#elif defined(HAVE_OPENSSL_ADD_ALL_ALGORITHMS)
OpenSSL_add_all_algorithms();
+#endif
+#ifdef USE_OPENSSL_ENGINE
/* Enable use of crypto hardware */
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
-#if OPENSSL_VERSION_NUMBER < 0x10001000L
- OPENSSL_config(NULL);
-#else
+ /* Load the libcrypto config file to pick up engines defined there */
+# if defined(HAVE_OPENSSL_INIT_CRYPTO) && defined(OPENSSL_INIT_LOAD_CONFIG)
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS |
OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL);
-#endif
+# else
+ OPENSSL_config(NULL);
+# endif
+#endif /* USE_OPENSSL_ENGINE */
}
-#endif
#endif /* WITH_OPENSSL */
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h
index 9e0264c04167..917bc6f7c278 100644
--- a/openbsd-compat/openssl-compat.h
+++ b/openbsd-compat/openssl-compat.h
@@ -1,236 +1,233 @@
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _OPENSSL_COMPAT_H
#define _OPENSSL_COMPAT_H
#include "includes.h"
#ifdef WITH_OPENSSL
#include <openssl/opensslv.h>
+#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
+#ifdef OPENSSL_HAS_ECC
#include <openssl/ecdsa.h>
+#endif
#include <openssl/dh.h>
int ssh_compatible_openssl(long, long);
+void ssh_libcrypto_init(void);
+
+#if (OPENSSL_VERSION_NUMBER < 0x1000100fL)
+# error OpenSSL 1.0.1 or greater is required
+#endif
+
+#ifndef OPENSSL_VERSION
+# define OPENSSL_VERSION SSLEAY_VERSION
+#endif
+
+#ifndef HAVE_OPENSSL_VERSION
+# define OpenSSL_version(x) SSLeay_version(x)
+#endif
-#if (OPENSSL_VERSION_NUMBER <= 0x0090805fL)
-# error OpenSSL 0.9.8f or greater is required
+#ifndef HAVE_OPENSSL_VERSION_NUM
+# define OpenSSL_version_num SSLeay
#endif
#if OPENSSL_VERSION_NUMBER < 0x10000001L
# define LIBCRYPTO_EVP_INL_TYPE unsigned int
#else
# define LIBCRYPTO_EVP_INL_TYPE size_t
#endif
#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
#endif
#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
#endif
#ifndef OPENSSL_HAVE_EVPCTR
# define EVP_aes_128_ctr evp_aes_128_ctr
# define EVP_aes_192_ctr evp_aes_128_ctr
# define EVP_aes_256_ctr evp_aes_128_ctr
const EVP_CIPHER *evp_aes_128_ctr(void);
void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
#endif
/* Avoid some #ifdef. Code that uses these is unreachable without GCM */
#if !defined(OPENSSL_HAVE_EVPGCM) && !defined(EVP_CTRL_GCM_SET_IV_FIXED)
# define EVP_CTRL_GCM_SET_IV_FIXED -1
# define EVP_CTRL_GCM_IV_GEN -1
# define EVP_CTRL_GCM_SET_TAG -1
# define EVP_CTRL_GCM_GET_TAG -1
#endif
/* Replace missing EVP_CIPHER_CTX_ctrl() with something that returns failure */
#ifndef HAVE_EVP_CIPHER_CTX_CTRL
# ifdef OPENSSL_HAVE_EVPGCM
# error AES-GCM enabled without EVP_CIPHER_CTX_ctrl /* shouldn't happen */
# else
# define EVP_CIPHER_CTX_ctrl(a,b,c,d) (0)
# endif
#endif
#if defined(HAVE_EVP_RIPEMD160)
# if defined(OPENSSL_NO_RIPEMD) || defined(OPENSSL_NO_RMD160)
# undef HAVE_EVP_RIPEMD160
# endif
#endif
-/*
- * We overload some of the OpenSSL crypto functions with ssh_* equivalents
- * to automatically handle OpenSSL engine initialisation.
- *
- * In order for the compat library to call the real functions, it must
- * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and
- * implement the ssh_* equivalents.
- */
-#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS
-
-# ifdef USE_OPENSSL_ENGINE
-# ifdef OpenSSL_add_all_algorithms
-# undef OpenSSL_add_all_algorithms
-# endif
-# define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms()
-# endif
-
-void ssh_OpenSSL_add_all_algorithms(void);
-
-#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */
-
/* LibreSSL/OpenSSL 1.1x API compat */
#ifndef HAVE_DSA_GET0_PQG
void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q,
const BIGNUM **g);
#endif /* HAVE_DSA_GET0_PQG */
#ifndef HAVE_DSA_SET0_PQG
int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
#endif /* HAVE_DSA_SET0_PQG */
#ifndef HAVE_DSA_GET0_KEY
void DSA_get0_key(const DSA *d, const BIGNUM **pub_key,
const BIGNUM **priv_key);
#endif /* HAVE_DSA_GET0_KEY */
#ifndef HAVE_DSA_SET0_KEY
int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
#endif /* HAVE_DSA_SET0_KEY */
#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx,
unsigned char *iv, size_t len);
#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
#ifndef HAVE_EVP_CIPHER_CTX_SET_IV
int EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx,
const unsigned char *iv, size_t len);
#endif /* HAVE_EVP_CIPHER_CTX_SET_IV */
#ifndef HAVE_RSA_GET0_KEY
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e,
const BIGNUM **d);
#endif /* HAVE_RSA_GET0_KEY */
#ifndef HAVE_RSA_SET0_KEY
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
#endif /* HAVE_RSA_SET0_KEY */
#ifndef HAVE_RSA_GET0_CRT_PARAMS
void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1,
const BIGNUM **iqmp);
#endif /* HAVE_RSA_GET0_CRT_PARAMS */
#ifndef HAVE_RSA_SET0_CRT_PARAMS
int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
#endif /* HAVE_RSA_SET0_CRT_PARAMS */
#ifndef HAVE_RSA_GET0_FACTORS
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
#endif /* HAVE_RSA_GET0_FACTORS */
#ifndef HAVE_RSA_SET0_FACTORS
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
#endif /* HAVE_RSA_SET0_FACTORS */
#ifndef DSA_SIG_GET0
void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
#endif /* DSA_SIG_GET0 */
#ifndef DSA_SIG_SET0
int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
#endif /* DSA_SIG_SET0 */
+#ifdef OPENSSL_HAS_ECC
#ifndef HAVE_ECDSA_SIG_GET0
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
#endif /* HAVE_ECDSA_SIG_GET0 */
#ifndef HAVE_ECDSA_SIG_SET0
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
#endif /* HAVE_ECDSA_SIG_SET0 */
+#endif /* OPENSSL_HAS_ECC */
#ifndef HAVE_DH_GET0_PQG
void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q,
const BIGNUM **g);
#endif /* HAVE_DH_GET0_PQG */
#ifndef HAVE_DH_SET0_PQG
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
#endif /* HAVE_DH_SET0_PQG */
#ifndef HAVE_DH_GET0_KEY
void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
#endif /* HAVE_DH_GET0_KEY */
#ifndef HAVE_DH_SET0_KEY
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
#endif /* HAVE_DH_SET0_KEY */
#ifndef HAVE_DH_SET_LENGTH
int DH_set_length(DH *dh, long length);
#endif /* HAVE_DH_SET_LENGTH */
#ifndef HAVE_RSA_METH_FREE
void RSA_meth_free(RSA_METHOD *meth);
#endif /* HAVE_RSA_METH_FREE */
#ifndef HAVE_RSA_METH_DUP
RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
#endif /* HAVE_RSA_METH_DUP */
#ifndef HAVE_RSA_METH_SET1_NAME
int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
#endif /* HAVE_RSA_METH_SET1_NAME */
#ifndef HAVE_RSA_METH_GET_FINISH
int (*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa);
#endif /* HAVE_RSA_METH_GET_FINISH */
#ifndef HAVE_RSA_METH_SET_PRIV_ENC
int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen,
const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
#endif /* HAVE_RSA_METH_SET_PRIV_ENC */
#ifndef HAVE_RSA_METH_SET_PRIV_DEC
int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen,
const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
#endif /* HAVE_RSA_METH_SET_PRIV_DEC */
#ifndef HAVE_RSA_METH_SET_FINISH
int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa));
#endif /* HAVE_RSA_METH_SET_FINISH */
#ifndef HAVE_EVP_PKEY_GET0_RSA
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
#endif /* HAVE_EVP_PKEY_GET0_RSA */
#ifndef HAVE_EVP_MD_CTX_new
EVP_MD_CTX *EVP_MD_CTX_new(void);
#endif /* HAVE_EVP_MD_CTX_new */
#ifndef HAVE_EVP_MD_CTX_free
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
#endif /* HAVE_EVP_MD_CTX_free */
#endif /* WITH_OPENSSL */
#endif /* _OPENSSL_COMPAT_H */
diff --git a/openbsd-compat/port-aix.c b/openbsd-compat/port-aix.c
index 943177c708c9..fc80dc39f96f 100644
--- a/openbsd-compat/port-aix.c
+++ b/openbsd-compat/port-aix.c
@@ -1,480 +1,481 @@
/*
*
* Copyright (c) 2001 Gert Doering. All rights reserved.
* Copyright (c) 2003,2004,2005,2006 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "includes.h"
#include "xmalloc.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "sshkey.h"
#include "hostfile.h"
#include "auth.h"
#include "ssh.h"
#include "ssh_api.h"
#include "log.h"
#ifdef _AIX
#include <errno.h>
#if defined(HAVE_NETDB_H)
# include <netdb.h>
#endif
#include <uinfo.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#ifdef WITH_AIXAUTHENTICATE
# include <login.h>
# include <userpw.h>
# if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG)
# include <sys/audit.h>
# endif
# include <usersec.h>
#endif
#include "port-aix.h"
static char *lastlogin_msg = NULL;
# ifdef HAVE_SETAUTHDB
static char old_registry[REGISTRY_SIZE] = "";
# endif
/*
* AIX has a "usrinfo" area where logname and other stuff is stored -
* a few applications actually use this and die if it's not set
*
* NOTE: TTY= should be set, but since no one uses it and it's hard to
* acquire due to privsep code. We will just drop support.
*/
void
aix_usrinfo(struct passwd *pw)
{
u_int i;
size_t len;
char *cp;
len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name));
cp = xmalloc(len);
i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0',
pw->pw_name, '\0');
if (usrinfo(SETUINFO, cp, i) == -1)
fatal("Couldn't set usrinfo: %s", strerror(errno));
debug3("AIX/UsrInfo: set len %d", i);
free(cp);
}
# ifdef WITH_AIXAUTHENTICATE
/*
* Remove embedded newlines in string (if any).
* Used before logging messages returned by AIX authentication functions
* so the message is logged on one line.
*/
void
aix_remove_embedded_newlines(char *p)
{
if (p == NULL)
return;
for (; *p; p++) {
if (*p == '\n')
*p = ' ';
}
/* Remove trailing whitespace */
if (*--p == ' ')
*p = '\0';
}
/*
* Test specifically for the case where SYSTEM == NONE and AUTH1 contains
* anything other than NONE or SYSTEM, which indicates that the admin has
* configured the account for purely AUTH1-type authentication.
*
* Since authenticate() doesn't check AUTH1, and sshd can't sanely support
* AUTH1 itself, in such a case authenticate() will allow access without
* authentation, which is almost certainly not what the admin intends.
*
* (The native tools, eg login, will process the AUTH1 list in addition to
* the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods
* have been deprecated since AIX 4.2.x and would be very difficult for sshd
* to support.
*
* Returns 0 if an unsupportable combination is found, 1 otherwise.
*/
static int
aix_valid_authentications(const char *user)
{
char *auth1, *sys, *p;
int valid = 1;
if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) {
logit("Can't retrieve attribute SYSTEM for %s: %.100s",
user, strerror(errno));
return 0;
}
debug3("AIX SYSTEM attribute %s", sys);
if (strcmp(sys, "NONE") != 0)
return 1; /* not "NONE", so is OK */
if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) {
logit("Can't retrieve attribute auth1 for %s: %.100s",
user, strerror(errno));
return 0;
}
p = auth1;
/* A SEC_LIST is concatenated strings, ending with two NULs. */
while (p[0] != '\0' && p[1] != '\0') {
debug3("AIX auth1 attribute list member %s", p);
if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) {
logit("Account %s has unsupported auth1 value '%s'",
user, p);
valid = 0;
}
p += strlen(p) + 1;
}
return (valid);
}
/*
* Do authentication via AIX's authenticate routine. We loop until the
* reenter parameter is 0, but normally authenticate is called only once.
*
* Note: this function returns 1 on success, whereas AIX's authenticate()
* returns 0.
*/
int
sys_auth_passwd(struct ssh *ssh, const char *password)
{
Authctxt *ctxt = ssh->authctxt;
char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name;
int r, authsuccess = 0, expired, reenter, result;
do {
result = authenticate((char *)name, (char *)password, &reenter,
&authmsg);
aix_remove_embedded_newlines(authmsg);
debug3("AIX/authenticate result %d, authmsg %.100s", result,
authmsg);
} while (reenter);
if (!aix_valid_authentications(name))
result = -1;
if (result == 0) {
authsuccess = 1;
/*
* Record successful login. We don't have a pty yet, so just
* label the line as "ssh"
*/
aix_setauthdb(name);
/*
* Check if the user's password is expired.
*/
expired = passwdexpired(name, &msg);
if (msg && *msg) {
if ((r = sshbuf_put(ctxt->loginmsg,
msg, strlen(msg))) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
aix_remove_embedded_newlines(msg);
}
debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg);
switch (expired) {
case 0: /* password not expired */
break;
case 1: /* expired, password change required */
ctxt->force_pwchange = 1;
break;
default: /* user can't change(2) or other error (-1) */
logit("Password can't be changed for user %s: %.100s",
name, msg);
free(msg);
authsuccess = 0;
}
aix_restoreauthdb();
}
free(authmsg);
return authsuccess;
}
/*
* Check if specified account is permitted to log in.
* Returns 1 if login is allowed, 0 if not allowed.
*/
int
sys_auth_allowed_user(struct passwd *pw, struct sshbuf *loginmsg)
{
char *msg = NULL;
int r, result, permitted = 0;
struct stat st;
/*
* Don't perform checks for root account (PermitRootLogin controls
* logins via ssh) or if running as non-root user (since
* loginrestrictions will always fail due to insufficient privilege).
*/
if (pw->pw_uid == 0 || geteuid() != 0) {
debug3("%s: not checking", __func__);
return 1;
}
result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg);
if (result == 0)
permitted = 1;
/*
* If restricted because /etc/nologin exists, the login will be denied
* in session.c after the nologin message is sent, so allow for now
* and do not append the returned message.
*/
if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0)
permitted = 1;
else if (msg != NULL) {
if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if (msg == NULL)
msg = xstrdup("(none)");
aix_remove_embedded_newlines(msg);
debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg);
if (!permitted)
logit("Login restricted for %s: %.100s", pw->pw_name, msg);
free(msg);
return permitted;
}
int
sys_auth_record_login(const char *user, const char *host, const char *ttynm,
struct sshbuf *loginmsg)
{
char *msg = NULL;
int success = 0;
aix_setauthdb(user);
if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) {
success = 1;
if (msg != NULL) {
debug("AIX/loginsuccess: msg %s", msg);
if (lastlogin_msg == NULL)
lastlogin_msg = msg;
}
}
aix_restoreauthdb();
return (success);
}
char *
sys_auth_get_lastlogin_msg(const char *user, uid_t uid)
{
char *msg = lastlogin_msg;
lastlogin_msg = NULL;
return msg;
}
# ifdef CUSTOM_FAILED_LOGIN
/*
* record_failed_login: generic "login failed" interface function
*/
void
-record_failed_login(const char *user, const char *hostname, const char *ttyname)
+record_failed_login(struct ssh *ssh, const char *user, const char *hostname,
+ const char *ttyname)
{
if (geteuid() != 0)
return;
aix_setauthdb(user);
# ifdef AIX_LOGINFAILED_4ARG
loginfailed((char *)user, (char *)hostname, (char *)ttyname,
AUDIT_FAIL_AUTH);
# else
loginfailed((char *)user, (char *)hostname, (char *)ttyname);
# endif
aix_restoreauthdb();
}
# endif /* CUSTOM_FAILED_LOGIN */
/*
* If we have setauthdb, retrieve the password registry for the user's
* account then feed it to setauthdb. This will mean that subsequent AIX auth
* functions will only use the specified loadable module. If we don't have
* setauthdb this is a no-op.
*/
void
aix_setauthdb(const char *user)
{
# ifdef HAVE_SETAUTHDB
char *registry;
if (setuserdb(S_READ) == -1) {
debug3("%s: Could not open userdb to read", __func__);
return;
}
if (getuserattr((char *)user, S_REGISTRY, &registry, SEC_CHAR) == 0) {
if (setauthdb(registry, old_registry) == 0)
debug3("AIX/setauthdb set registry '%s'", registry);
else
debug3("AIX/setauthdb set registry '%s' failed: %s",
registry, strerror(errno));
} else
debug3("%s: Could not read S_REGISTRY for user: %s", __func__,
strerror(errno));
enduserdb();
# endif /* HAVE_SETAUTHDB */
}
/*
* Restore the user's registry settings from old_registry.
* Note that if the first aix_setauthdb fails, setauthdb("") is still safe
* (it restores the system default behaviour). If we don't have setauthdb,
* this is a no-op.
*/
void
aix_restoreauthdb(void)
{
# ifdef HAVE_SETAUTHDB
if (setauthdb(old_registry, NULL) == 0)
debug3("%s: restoring old registry '%s'", __func__,
old_registry);
else
debug3("%s: failed to restore old registry %s", __func__,
old_registry);
# endif /* HAVE_SETAUTHDB */
}
# endif /* WITH_AIXAUTHENTICATE */
# ifdef USE_AIX_KRB_NAME
/*
* aix_krb5_get_principal_name: returns the user's kerberos client principal name if
* configured, otherwise NULL. Caller must free returned string.
*/
char *
aix_krb5_get_principal_name(char *pw_name)
{
char *authname = NULL, *authdomain = NULL, *principal = NULL;
setuserdb(S_READ);
if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0)
debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno));
if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0)
debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno));
if (authdomain != NULL)
xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain);
else if (authname != NULL)
principal = xstrdup(authname);
enduserdb();
return principal;
}
# endif /* USE_AIX_KRB_NAME */
# if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO)
# undef getnameinfo
/*
* For some reason, AIX's getnameinfo will refuse to resolve the all-zeros
* IPv6 address into its textual representation ("::"), so we wrap it
* with a function that will.
*/
int
sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
size_t hostlen, char *serv, size_t servlen, int flags)
{
struct sockaddr_in6 *sa6;
u_int32_t *a6;
if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) &&
sa->sa_family == AF_INET6) {
sa6 = (struct sockaddr_in6 *)sa;
a6 = sa6->sin6_addr.u6_addr.u6_addr32;
if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
strlcpy(host, "::", hostlen);
snprintf(serv, servlen, "%d", sa6->sin6_port);
return 0;
}
}
return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
}
# endif /* AIX_GETNAMEINFO_HACK */
# if defined(USE_GETGRSET)
# include <stdlib.h>
int
getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt)
{
char *cp, *grplist, *grp;
gid_t gid;
int ret = 0, ngroups = 0, maxgroups;
long l;
maxgroups = *grpcnt;
if ((cp = grplist = getgrset(user)) == NULL)
return -1;
/* handle zero-length case */
if (maxgroups <= 0) {
*grpcnt = 0;
return -1;
}
/* copy primary group */
groups[ngroups++] = pgid;
/* copy each entry from getgrset into group list */
while ((grp = strsep(&grplist, ",")) != NULL) {
l = strtol(grp, NULL, 10);
if (ngroups >= maxgroups || l == LONG_MIN || l == LONG_MAX) {
ret = -1;
goto out;
}
gid = (gid_t)l;
if (gid == pgid)
continue; /* we have already added primary gid */
groups[ngroups++] = gid;
}
out:
free(cp);
*grpcnt = ngroups;
return ret;
}
# endif /* USE_GETGRSET */
#endif /* _AIX */
diff --git a/openbsd-compat/port-aix.h b/openbsd-compat/port-aix.h
index 748c0e4e3109..904de30969c6 100644
--- a/openbsd-compat/port-aix.h
+++ b/openbsd-compat/port-aix.h
@@ -1,126 +1,127 @@
/*
*
* Copyright (c) 2001 Gert Doering. All rights reserved.
* Copyright (c) 2004,2005,2006 Darren Tucker. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef _AIX
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
+struct ssh;
struct sshbuf;
/* These should be in the system headers but are not. */
int usrinfo(int, char *, int);
#if defined(HAVE_DECL_SETAUTHDB) && (HAVE_DECL_SETAUTHDB == 0)
int setauthdb(const char *, char *);
#endif
/* these may or may not be in the headers depending on the version */
#if defined(HAVE_DECL_AUTHENTICATE) && (HAVE_DECL_AUTHENTICATE == 0)
int authenticate(char *, char *, int *, char **);
#endif
#if defined(HAVE_DECL_LOGINFAILED) && (HAVE_DECL_LOGINFAILED == 0)
int loginfailed(char *, char *, char *);
#endif
#if defined(HAVE_DECL_LOGINRESTRICTIONS) && (HAVE_DECL_LOGINRESTRICTIONS == 0)
int loginrestrictions(char *, int, char *, char **);
#endif
#if defined(HAVE_DECL_LOGINSUCCESS) && (HAVE_DECL_LOGINSUCCESS == 0)
int loginsuccess(char *, char *, char *, char **);
#endif
#if defined(HAVE_DECL_PASSWDEXPIRED) && (HAVE_DECL_PASSWDEXPIRED == 0)
int passwdexpired(char *, char **);
#endif
/* Some versions define r_type in the above headers, which causes a conflict */
#ifdef r_type
# undef r_type
#endif
/* AIX 4.2.x doesn't have nanosleep but does have nsleep which is equivalent */
#if !defined(HAVE_NANOSLEEP) && defined(HAVE_NSLEEP)
# define nanosleep(a,b) nsleep(a,b)
#endif
/* For struct timespec on AIX 4.2.x */
#ifdef HAVE_SYS_TIMERS_H
# include <sys/timers.h>
#endif
/* for setpcred and friends */
#ifdef HAVE_USERSEC_H
# include <usersec.h>
#endif
/*
* According to the setauthdb man page, AIX password registries must be 15
* chars or less plus terminating NUL.
*/
#ifdef HAVE_SETAUTHDB
# define REGISTRY_SIZE 16
#endif
void aix_usrinfo(struct passwd *);
#ifdef WITH_AIXAUTHENTICATE
# define CUSTOM_SYS_AUTH_PASSWD 1
# define CUSTOM_SYS_AUTH_ALLOWED_USER 1
int sys_auth_allowed_user(struct passwd *, struct sshbuf *);
# define CUSTOM_SYS_AUTH_RECORD_LOGIN 1
-int sys_auth_record_login(const char *, const char *,
- const char *, struct sshbuf *);
+int sys_auth_record_login(const char *, const char *, const char *,
+ struct sshbuf *);
# define CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG
char *sys_auth_get_lastlogin_msg(const char *, uid_t);
# define CUSTOM_FAILED_LOGIN 1
# if defined(S_AUTHDOMAIN) && defined (S_AUTHNAME)
# define USE_AIX_KRB_NAME
char *aix_krb5_get_principal_name(char *);
# endif
#endif
void aix_setauthdb(const char *);
void aix_restoreauthdb(void);
void aix_remove_embedded_newlines(char *);
#if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_GETADDRINFO)
# ifdef getnameinfo
# undef getnameinfo
# endif
int sshaix_getnameinfo(const struct sockaddr *, size_t, char *, size_t,
char *, size_t, int);
# define getnameinfo(a,b,c,d,e,f,g) (sshaix_getnameinfo(a,b,c,d,e,f,g))
#endif
/*
* We use getgrset in preference to multiple getgrent calls for efficiency
* plus it supports NIS and LDAP groups.
*/
#if !defined(HAVE_GETGROUPLIST) && defined(HAVE_GETGRSET)
# define HAVE_GETGROUPLIST
# define USE_GETGRSET
int getgrouplist(const char *, gid_t, gid_t *, int *);
#endif
#endif /* _AIX */
diff --git a/openbsd-compat/regress/Makefile.in b/openbsd-compat/regress/Makefile.in
index 529331be5c26..c5aae61e2a42 100644
--- a/openbsd-compat/regress/Makefile.in
+++ b/openbsd-compat/regress/Makefile.in
@@ -1,36 +1,36 @@
sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
VPATH=@srcdir@
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
EXEEXT=@EXEEXT@
LIBCOMPAT=../libopenbsd-compat.a
LIBS=@LIBS@
LDFLAGS=@LDFLAGS@ $(LIBCOMPAT)
TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \
- strtonumtest$(EXEEXT) opensslvertest$(EXEEXT)
+ strtonumtest$(EXEEXT) opensslvertest$(EXEEXT) utimensattest$(EXEEXT)
all: t-exec ${OTHERTESTS}
%$(EXEEXT): %.c $(LIBCOMPAT)
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS)
t-exec: $(TESTPROGS)
@echo running compat regress tests
@for TEST in ""$?; do \
echo "run test $${TEST}" ... 1>&2; \
./$${TEST}$(EXEEXT) || exit $$? ; \
done
@echo finished compat regress tests
clean:
rm -f *.o *.a core $(TESTPROGS) valid.out
distclean: clean
rm -f Makefile *~
diff --git a/openbsd-compat/regress/utimensattest.c b/openbsd-compat/regress/utimensattest.c
new file mode 100644
index 000000000000..a7bc7634b571
--- /dev/null
+++ b/openbsd-compat/regress/utimensattest.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2019 Darren Tucker
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define TMPFILE "utimensat.tmp"
+#define TMPFILE2 "utimensat.tmp2"
+
+#ifndef AT_SYMLINK_NOFOLLOW
+# define AT_SYMLINK_NOFOLLOW 0x80000000
+#endif
+
+int utimensat(int, const char *, const struct timespec[2], int);
+
+void
+fail(char *msg, long expect, long got)
+{
+ int saved_errno = errno;
+
+ if (expect == got && got == 0)
+ fprintf(stderr, "utimensat: %s: %s\n", msg,
+ strerror(saved_errno));
+ else
+ fprintf(stderr, "utimensat: %s: expected %ld got %ld\n",
+ msg, expect, got);
+ exit(1);
+}
+
+int
+main(void)
+{
+ int fd;
+ struct stat sb;
+ struct timespec ts[2];
+
+ if ((fd = open(TMPFILE, O_CREAT, 0600)) == -1)
+ fail("open", 0, 0);
+ close(fd);
+
+ ts[0].tv_sec = 12345678;
+ ts[0].tv_nsec = 23456789;
+ ts[1].tv_sec = 34567890;
+ ts[1].tv_nsec = 45678901;
+ if (utimensat(AT_FDCWD, TMPFILE, ts, AT_SYMLINK_NOFOLLOW) == -1)
+ fail("utimensat", 0, 0);
+
+ if (stat(TMPFILE, &sb) == -1)
+ fail("stat", 0, 0 );
+ if (sb.st_atime != 12345678)
+ fail("st_atime", 0, 0 );
+ if (sb.st_mtime != 34567890)
+ fail("st_mtime", 0, 0 );
+#if 0
+ /*
+ * Results expected to be rounded to the nearest microsecond.
+ * Depends on timestamp precision in kernel and filesystem so
+ * disabled by default.
+ */
+ if (sb.st_atim.tv_nsec != 23456000)
+ fail("atim.tv_nsec", 23456000, sb.st_atim.tv_nsec);
+ if (sb.st_mtim.tv_nsec != 45678000)
+ fail("mtim.tv_nsec", 45678000, sb.st_mtim.tv_nsec);
+#endif
+
+ if (rename(TMPFILE, TMPFILE2) == -1)
+ fail("rename", 0, 0);
+ if (symlink(TMPFILE2, TMPFILE) == -1)
+ fail("symlink", 0, 0);
+
+ if (utimensat(AT_FDCWD, TMPFILE, ts, AT_SYMLINK_NOFOLLOW) != -1)
+ fail("utimensat followed symlink", 0, 0);
+
+ if (!(unlink(TMPFILE) == 0 && unlink(TMPFILE2) == 0))
+ fail("unlink", 0, 0);
+ exit(0);
+}
diff --git a/openbsd-compat/sys-queue.h b/openbsd-compat/sys-queue.h
index af93d6814025..5108f394c543 100644
--- a/openbsd-compat/sys-queue.h
+++ b/openbsd-compat/sys-queue.h
@@ -1,658 +1,659 @@
/* $OpenBSD: queue.h,v 1.36 2012/04/11 13:29:14 naddy Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
/* OPENBSD ORIGINAL: sys/sys/queue.h */
#ifndef _FAKE_QUEUE_H_
#define _FAKE_QUEUE_H_
/*
* Require for OS/X and other platforms that have old/broken/incomplete
* <sys/queue.h>.
*/
#undef SLIST_HEAD
#undef SLIST_HEAD_INITIALIZER
#undef SLIST_ENTRY
#undef SLIST_FOREACH_PREVPTR
#undef SLIST_FOREACH_SAFE
#undef SLIST_FIRST
#undef SLIST_END
#undef SLIST_EMPTY
#undef SLIST_NEXT
#undef SLIST_FOREACH
#undef SLIST_INIT
#undef SLIST_INSERT_AFTER
#undef SLIST_INSERT_HEAD
#undef SLIST_REMOVE_HEAD
#undef SLIST_REMOVE_AFTER
#undef SLIST_REMOVE
#undef SLIST_REMOVE_NEXT
#undef LIST_HEAD
#undef LIST_HEAD_INITIALIZER
#undef LIST_ENTRY
#undef LIST_FIRST
#undef LIST_END
#undef LIST_EMPTY
#undef LIST_NEXT
#undef LIST_FOREACH
#undef LIST_FOREACH_SAFE
#undef LIST_INIT
#undef LIST_INSERT_AFTER
#undef LIST_INSERT_BEFORE
#undef LIST_INSERT_HEAD
#undef LIST_REMOVE
#undef LIST_REPLACE
#undef SIMPLEQ_HEAD
#undef SIMPLEQ_HEAD_INITIALIZER
#undef SIMPLEQ_ENTRY
#undef SIMPLEQ_FIRST
#undef SIMPLEQ_END
#undef SIMPLEQ_EMPTY
#undef SIMPLEQ_NEXT
#undef SIMPLEQ_FOREACH
+#undef SIMPLEQ_FOREACH_SAFE
#undef SIMPLEQ_INIT
#undef SIMPLEQ_INSERT_HEAD
#undef SIMPLEQ_INSERT_TAIL
#undef SIMPLEQ_INSERT_AFTER
#undef SIMPLEQ_REMOVE_HEAD
#undef TAILQ_HEAD
#undef TAILQ_HEAD_INITIALIZER
#undef TAILQ_ENTRY
#undef TAILQ_FIRST
#undef TAILQ_END
#undef TAILQ_NEXT
#undef TAILQ_LAST
#undef TAILQ_PREV
#undef TAILQ_EMPTY
#undef TAILQ_FOREACH
#undef TAILQ_FOREACH_REVERSE
#undef TAILQ_FOREACH_SAFE
#undef TAILQ_FOREACH_REVERSE_SAFE
#undef TAILQ_INIT
#undef TAILQ_INSERT_HEAD
#undef TAILQ_INSERT_TAIL
#undef TAILQ_INSERT_AFTER
#undef TAILQ_INSERT_BEFORE
#undef TAILQ_REMOVE
#undef TAILQ_REPLACE
#undef CIRCLEQ_HEAD
#undef CIRCLEQ_HEAD_INITIALIZER
#undef CIRCLEQ_ENTRY
#undef CIRCLEQ_FIRST
#undef CIRCLEQ_LAST
#undef CIRCLEQ_END
#undef CIRCLEQ_NEXT
#undef CIRCLEQ_PREV
#undef CIRCLEQ_EMPTY
#undef CIRCLEQ_FOREACH
#undef CIRCLEQ_FOREACH_REVERSE
#undef CIRCLEQ_INIT
#undef CIRCLEQ_INSERT_AFTER
#undef CIRCLEQ_INSERT_BEFORE
#undef CIRCLEQ_INSERT_HEAD
#undef CIRCLEQ_INSERT_TAIL
#undef CIRCLEQ_REMOVE
#undef CIRCLEQ_REPLACE
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
#else
#define _Q_INVALIDATE(a)
#endif
/*
* Singly-linked List definitions.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST(head); \
(var) && ((tvar) = SLIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Singly-linked List functions.
*/
#define SLIST_INIT(head) { \
SLIST_FIRST(head) = SLIST_END(head); \
}
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
#define SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->slh_first; \
\
while (curelm->field.sle_next != (elm)) \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
_Q_INVALIDATE((elm)->field.sle_next); \
} \
} while (0)
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST(head); \
(var) && ((tvar) = LIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue access methods.
*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SIMPLEQ_FIRST(head); \
(var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
== NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* tail queue access methods
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
/* XXX */
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) \
(TAILQ_FIRST(head) == TAILQ_END(head))
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_NEXT(var, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
(elm2)->field.tqe_next->field.tqe_prev = \
&(elm2)->field.tqe_next; \
else \
(head)->tqh_last = &(elm2)->field.tqe_next; \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
/*
* Circular queue definitions.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue access methods
*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_END(head) ((void *)(head))
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
#define CIRCLEQ_EMPTY(head) \
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
#define CIRCLEQ_FOREACH(var, head, field) \
for((var) = CIRCLEQ_FIRST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_NEXT(var, field))
#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = CIRCLEQ_FIRST(head); \
(var) != CIRCLEQ_END(head) && \
((tvar) = CIRCLEQ_NEXT(var, field), 1); \
(var) = (tvar))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for((var) = CIRCLEQ_LAST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_PREV(var, field))
#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = CIRCLEQ_LAST(head, headname); \
(var) != CIRCLEQ_END(head) && \
((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) do { \
(head)->cqh_first = CIRCLEQ_END(head); \
(head)->cqh_last = CIRCLEQ_END(head); \
} while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
} while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
} while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
if ((head)->cqh_last == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
} while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.cqe_next = CIRCLEQ_END(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
} while (0)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
_Q_INVALIDATE((elm)->field.cqe_prev); \
_Q_INVALIDATE((elm)->field.cqe_next); \
} while (0)
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
CIRCLEQ_END(head)) \
(head).cqh_last = (elm2); \
else \
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
CIRCLEQ_END(head)) \
(head).cqh_first = (elm2); \
else \
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
_Q_INVALIDATE((elm)->field.cqe_prev); \
_Q_INVALIDATE((elm)->field.cqe_next); \
} while (0)
#endif /* !_FAKE_QUEUE_H_ */
diff --git a/packet.c b/packet.c
index dcf35e6e626a..36e352b4466d 100644
--- a/packet.c
+++ b/packet.c
@@ -1,2682 +1,2704 @@
-/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.283 2019/03/01 03:29:32 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This file contains code implementing the packet protocol and communication
* with the other side. This same code is used both on client and server side.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
*
* SSH2 packet format added by Markus Friedl.
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include "openbsd-compat/sys-queue.h"
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
+#include <poll.h>
#include <signal.h>
#include <time.h>
/*
* Explicitly include OpenSSL before zlib as some versions of OpenSSL have
* "free_func" in their headers, which zlib typedefs.
*/
#ifdef WITH_OPENSSL
# include <openssl/bn.h>
# include <openssl/evp.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# endif
#endif
#include <zlib.h>
#include "xmalloc.h"
#include "crc32.h"
#include "compat.h"
#include "ssh2.h"
#include "cipher.h"
#include "sshkey.h"
#include "kex.h"
#include "digest.h"
#include "mac.h"
#include "log.h"
#include "canohost.h"
#include "misc.h"
#include "channels.h"
#include "ssh.h"
#include "packet.h"
#include "ssherr.h"
#include "sshbuf.h"
#ifdef PACKET_DEBUG
#define DBG(x) x
#else
#define DBG(x)
#endif
#define PACKET_MAX_SIZE (256 * 1024)
struct packet_state {
u_int32_t seqnr;
u_int32_t packets;
u_int64_t blocks;
u_int64_t bytes;
};
struct packet {
TAILQ_ENTRY(packet) next;
u_char type;
struct sshbuf *payload;
};
struct session_state {
/*
* This variable contains the file descriptors used for
* communicating with the other side. connection_in is used for
* reading; connection_out for writing. These can be the same
* descriptor, in which case it is assumed to be a socket.
*/
int connection_in;
int connection_out;
/* Protocol flags for the remote side. */
u_int remote_protocol_flags;
/* Encryption context for receiving data. Only used for decryption. */
struct sshcipher_ctx *receive_context;
/* Encryption context for sending data. Only used for encryption. */
struct sshcipher_ctx *send_context;
/* Buffer for raw input data from the socket. */
struct sshbuf *input;
/* Buffer for raw output data going to the socket. */
struct sshbuf *output;
/* Buffer for the partial outgoing packet being constructed. */
struct sshbuf *outgoing_packet;
/* Buffer for the incoming packet currently being processed. */
struct sshbuf *incoming_packet;
/* Scratch buffer for packet compression/decompression. */
struct sshbuf *compression_buffer;
/* Incoming/outgoing compression dictionaries */
z_stream compression_in_stream;
z_stream compression_out_stream;
int compression_in_started;
int compression_out_started;
int compression_in_failures;
int compression_out_failures;
/* default maximum packet size */
u_int max_packet_size;
/* Flag indicating whether this module has been initialized. */
int initialized;
/* Set to true if the connection is interactive. */
int interactive_mode;
/* Set to true if we are the server side. */
int server_side;
/* Set to true if we are authenticated. */
int after_authentication;
int keep_alive_timeouts;
/* The maximum time that we will wait to send or receive a packet */
int packet_timeout_ms;
/* Session key information for Encryption and MAC */
struct newkeys *newkeys[MODE_MAX];
struct packet_state p_read, p_send;
/* Volume-based rekeying */
u_int64_t max_blocks_in, max_blocks_out, rekey_limit;
/* Time-based rekeying */
u_int32_t rekey_interval; /* how often in seconds */
time_t rekey_time; /* time of last rekeying */
/* roundup current message to extra_pad bytes */
u_char extra_pad;
/* XXX discard incoming data after MAC error */
u_int packet_discard;
size_t packet_discard_mac_already;
struct sshmac *packet_discard_mac;
/* Used in packet_read_poll2() */
u_int packlen;
/* Used in packet_send2 */
int rekeying;
/* Used in ssh_packet_send_mux() */
int mux;
/* Used in packet_set_interactive */
int set_interactive_called;
/* Used in packet_set_maxsize */
int set_maxsize_called;
/* One-off warning about weak ciphers */
int cipher_warning_done;
/* Hook for fuzzing inbound packets */
ssh_packet_hook_fn *hook_in;
void *hook_in_ctx;
TAILQ_HEAD(, packet) outgoing;
};
struct ssh *
ssh_alloc_session_state(void)
{
struct ssh *ssh = NULL;
struct session_state *state = NULL;
if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
(state = calloc(1, sizeof(*state))) == NULL ||
+ (ssh->kex = kex_new()) == NULL ||
(state->input = sshbuf_new()) == NULL ||
(state->output = sshbuf_new()) == NULL ||
(state->outgoing_packet = sshbuf_new()) == NULL ||
(state->incoming_packet = sshbuf_new()) == NULL)
goto fail;
TAILQ_INIT(&state->outgoing);
TAILQ_INIT(&ssh->private_keys);
TAILQ_INIT(&ssh->public_keys);
state->connection_in = -1;
state->connection_out = -1;
state->max_packet_size = 32768;
state->packet_timeout_ms = -1;
state->p_send.packets = state->p_read.packets = 0;
state->initialized = 1;
/*
* ssh_packet_send2() needs to queue packets until
* we've done the initial key exchange.
*/
state->rekeying = 1;
ssh->state = state;
return ssh;
fail:
+ if (ssh) {
+ kex_free(ssh->kex);
+ free(ssh);
+ }
if (state) {
sshbuf_free(state->input);
sshbuf_free(state->output);
sshbuf_free(state->incoming_packet);
sshbuf_free(state->outgoing_packet);
free(state);
}
- free(ssh);
return NULL;
}
void
ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
{
ssh->state->hook_in = hook;
ssh->state->hook_in_ctx = ctx;
}
/* Returns nonzero if rekeying is in progress */
int
ssh_packet_is_rekeying(struct ssh *ssh)
{
- return ssh->state->rekeying ||
- (ssh->kex != NULL && ssh->kex->done == 0);
+ return ssh->state->rekeying || ssh->kex->done == 0;
}
/*
* Sets the descriptors used for communication.
*/
struct ssh *
ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
{
struct session_state *state;
const struct sshcipher *none = cipher_by_name("none");
int r;
if (none == NULL) {
error("%s: cannot load cipher 'none'", __func__);
return NULL;
}
if (ssh == NULL)
ssh = ssh_alloc_session_state();
if (ssh == NULL) {
error("%s: cound not allocate state", __func__);
return NULL;
}
state = ssh->state;
state->connection_in = fd_in;
state->connection_out = fd_out;
if ((r = cipher_init(&state->send_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
(r = cipher_init(&state->receive_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
error("%s: cipher_init failed: %s", __func__, ssh_err(r));
free(ssh); /* XXX need ssh_free_session_state? */
return NULL;
}
state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
/*
* Cache the IP address of the remote connection for use in error
* messages that might be generated after the connection has closed.
*/
(void)ssh_remote_ipaddr(ssh);
return ssh;
}
void
ssh_packet_set_timeout(struct ssh *ssh, int timeout, int count)
{
struct session_state *state = ssh->state;
if (timeout <= 0 || count <= 0) {
state->packet_timeout_ms = -1;
return;
}
if ((INT_MAX / 1000) / count < timeout)
state->packet_timeout_ms = INT_MAX;
else
state->packet_timeout_ms = timeout * count * 1000;
}
void
ssh_packet_set_mux(struct ssh *ssh)
{
ssh->state->mux = 1;
ssh->state->rekeying = 0;
}
int
ssh_packet_get_mux(struct ssh *ssh)
{
return ssh->state->mux;
}
int
ssh_packet_set_log_preamble(struct ssh *ssh, const char *fmt, ...)
{
va_list args;
int r;
free(ssh->log_preamble);
if (fmt == NULL)
ssh->log_preamble = NULL;
else {
va_start(args, fmt);
r = vasprintf(&ssh->log_preamble, fmt, args);
va_end(args);
if (r < 0 || ssh->log_preamble == NULL)
return SSH_ERR_ALLOC_FAIL;
}
return 0;
}
int
ssh_packet_stop_discard(struct ssh *ssh)
{
struct session_state *state = ssh->state;
int r;
if (state->packet_discard_mac) {
char buf[1024];
size_t dlen = PACKET_MAX_SIZE;
if (dlen > state->packet_discard_mac_already)
dlen -= state->packet_discard_mac_already;
memset(buf, 'a', sizeof(buf));
while (sshbuf_len(state->incoming_packet) < dlen)
if ((r = sshbuf_put(state->incoming_packet, buf,
sizeof(buf))) != 0)
return r;
(void) mac_compute(state->packet_discard_mac,
state->p_read.seqnr,
sshbuf_ptr(state->incoming_packet), dlen,
NULL, 0);
}
logit("Finished discarding for %.200s port %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
return SSH_ERR_MAC_INVALID;
}
static int
ssh_packet_start_discard(struct ssh *ssh, struct sshenc *enc,
struct sshmac *mac, size_t mac_already, u_int discard)
{
struct session_state *state = ssh->state;
int r;
if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) {
if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
return r;
return SSH_ERR_MAC_INVALID;
}
/*
* Record number of bytes over which the mac has already
* been computed in order to minimize timing attacks.
*/
if (mac && mac->enabled) {
state->packet_discard_mac = mac;
state->packet_discard_mac_already = mac_already;
}
if (sshbuf_len(state->input) >= discard)
return ssh_packet_stop_discard(ssh);
state->packet_discard = discard - sshbuf_len(state->input);
return 0;
}
/* Returns 1 if remote host is connected via socket, 0 if not. */
int
ssh_packet_connection_is_on_socket(struct ssh *ssh)
{
struct session_state *state;
struct sockaddr_storage from, to;
socklen_t fromlen, tolen;
if (ssh == NULL || ssh->state == NULL)
return 0;
state = ssh->state;
if (state->connection_in == -1 || state->connection_out == -1)
return 0;
/* filedescriptors in and out are the same, so it's a socket */
if (state->connection_in == state->connection_out)
return 1;
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
if (getpeername(state->connection_in, (struct sockaddr *)&from,
&fromlen) < 0)
return 0;
tolen = sizeof(to);
memset(&to, 0, sizeof(to));
if (getpeername(state->connection_out, (struct sockaddr *)&to,
&tolen) < 0)
return 0;
if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)
return 0;
if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
return 0;
return 1;
}
void
ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes)
{
if (ibytes)
*ibytes = ssh->state->p_read.bytes;
if (obytes)
*obytes = ssh->state->p_send.bytes;
}
int
ssh_packet_connection_af(struct ssh *ssh)
{
struct sockaddr_storage to;
socklen_t tolen = sizeof(to);
memset(&to, 0, sizeof(to));
if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to,
&tolen) < 0)
return 0;
#ifdef IPV4_IN_IPV6
if (to.ss_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
return AF_INET;
#endif
return to.ss_family;
}
/* Sets the connection into non-blocking mode. */
void
ssh_packet_set_nonblocking(struct ssh *ssh)
{
/* Set the socket into non-blocking mode. */
set_nonblock(ssh->state->connection_in);
if (ssh->state->connection_out != ssh->state->connection_in)
set_nonblock(ssh->state->connection_out);
}
/* Returns the socket used for reading. */
int
ssh_packet_get_connection_in(struct ssh *ssh)
{
return ssh->state->connection_in;
}
/* Returns the descriptor used for writing. */
int
ssh_packet_get_connection_out(struct ssh *ssh)
{
return ssh->state->connection_out;
}
/*
* Returns the IP-address of the remote host as a string. The returned
* string must not be freed.
*/
const char *
ssh_remote_ipaddr(struct ssh *ssh)
{
int sock;
/* Check whether we have cached the ipaddr. */
if (ssh->remote_ipaddr == NULL) {
if (ssh_packet_connection_is_on_socket(ssh)) {
sock = ssh->state->connection_in;
ssh->remote_ipaddr = get_peer_ipaddr(sock);
ssh->remote_port = get_peer_port(sock);
ssh->local_ipaddr = get_local_ipaddr(sock);
ssh->local_port = get_local_port(sock);
} else {
ssh->remote_ipaddr = strdup("UNKNOWN");
ssh->remote_port = 65535;
ssh->local_ipaddr = strdup("UNKNOWN");
ssh->local_port = 65535;
}
}
return ssh->remote_ipaddr;
}
/* Returns the port number of the remote host. */
int
ssh_remote_port(struct ssh *ssh)
{
(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
return ssh->remote_port;
}
/*
* Returns the IP-address of the local host as a string. The returned
* string must not be freed.
*/
const char *
ssh_local_ipaddr(struct ssh *ssh)
{
(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
return ssh->local_ipaddr;
}
/* Returns the port number of the local host. */
int
ssh_local_port(struct ssh *ssh)
{
(void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
return ssh->local_port;
}
/* Returns the routing domain of the input socket, or NULL if unavailable */
const char *
ssh_packet_rdomain_in(struct ssh *ssh)
{
if (ssh->rdomain_in != NULL)
return ssh->rdomain_in;
if (!ssh_packet_connection_is_on_socket(ssh))
return NULL;
ssh->rdomain_in = get_rdomain(ssh->state->connection_in);
return ssh->rdomain_in;
}
/* Closes the connection and clears and frees internal data structures. */
static void
ssh_packet_close_internal(struct ssh *ssh, int do_close)
{
struct session_state *state = ssh->state;
u_int mode;
if (!state->initialized)
return;
state->initialized = 0;
if (do_close) {
if (state->connection_in == state->connection_out) {
close(state->connection_out);
} else {
close(state->connection_in);
close(state->connection_out);
}
}
sshbuf_free(state->input);
sshbuf_free(state->output);
sshbuf_free(state->outgoing_packet);
sshbuf_free(state->incoming_packet);
for (mode = 0; mode < MODE_MAX; mode++) {
kex_free_newkeys(state->newkeys[mode]); /* current keys */
state->newkeys[mode] = NULL;
ssh_clear_newkeys(ssh, mode); /* next keys */
}
/* compression state is in shared mem, so we can only release it once */
if (do_close && state->compression_buffer) {
sshbuf_free(state->compression_buffer);
if (state->compression_out_started) {
z_streamp stream = &state->compression_out_stream;
debug("compress outgoing: "
"raw data %llu, compressed %llu, factor %.2f",
(unsigned long long)stream->total_in,
(unsigned long long)stream->total_out,
stream->total_in == 0 ? 0.0 :
(double) stream->total_out / stream->total_in);
if (state->compression_out_failures == 0)
deflateEnd(stream);
}
if (state->compression_in_started) {
z_streamp stream = &state->compression_in_stream;
debug("compress incoming: "
"raw data %llu, compressed %llu, factor %.2f",
(unsigned long long)stream->total_out,
(unsigned long long)stream->total_in,
stream->total_out == 0 ? 0.0 :
(double) stream->total_in / stream->total_out);
if (state->compression_in_failures == 0)
inflateEnd(stream);
}
}
cipher_free(state->send_context);
cipher_free(state->receive_context);
state->send_context = state->receive_context = NULL;
if (do_close) {
free(ssh->local_ipaddr);
ssh->local_ipaddr = NULL;
free(ssh->remote_ipaddr);
ssh->remote_ipaddr = NULL;
free(ssh->state);
ssh->state = NULL;
}
}
void
ssh_packet_close(struct ssh *ssh)
{
ssh_packet_close_internal(ssh, 1);
}
void
ssh_packet_clear_keys(struct ssh *ssh)
{
ssh_packet_close_internal(ssh, 0);
}
/* Sets remote side protocol flags. */
void
ssh_packet_set_protocol_flags(struct ssh *ssh, u_int protocol_flags)
{
ssh->state->remote_protocol_flags = protocol_flags;
}
/* Returns the remote protocol flags set earlier by the above function. */
u_int
ssh_packet_get_protocol_flags(struct ssh *ssh)
{
return ssh->state->remote_protocol_flags;
}
/*
* Starts packet compression from the next packet on in both directions.
* Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
*/
static int
ssh_packet_init_compression(struct ssh *ssh)
{
if (!ssh->state->compression_buffer &&
((ssh->state->compression_buffer = sshbuf_new()) == NULL))
return SSH_ERR_ALLOC_FAIL;
return 0;
}
static int
start_compression_out(struct ssh *ssh, int level)
{
if (level < 1 || level > 9)
return SSH_ERR_INVALID_ARGUMENT;
debug("Enabling compression at level %d.", level);
if (ssh->state->compression_out_started == 1)
deflateEnd(&ssh->state->compression_out_stream);
switch (deflateInit(&ssh->state->compression_out_stream, level)) {
case Z_OK:
ssh->state->compression_out_started = 1;
break;
case Z_MEM_ERROR:
return SSH_ERR_ALLOC_FAIL;
default:
return SSH_ERR_INTERNAL_ERROR;
}
return 0;
}
static int
start_compression_in(struct ssh *ssh)
{
if (ssh->state->compression_in_started == 1)
inflateEnd(&ssh->state->compression_in_stream);
switch (inflateInit(&ssh->state->compression_in_stream)) {
case Z_OK:
ssh->state->compression_in_started = 1;
break;
case Z_MEM_ERROR:
return SSH_ERR_ALLOC_FAIL;
default:
return SSH_ERR_INTERNAL_ERROR;
}
return 0;
}
/* XXX remove need for separate compression buffer */
static int
compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
{
u_char buf[4096];
int r, status;
if (ssh->state->compression_out_started != 1)
return SSH_ERR_INTERNAL_ERROR;
/* This case is not handled below. */
if (sshbuf_len(in) == 0)
return 0;
/* Input is the contents of the input buffer. */
if ((ssh->state->compression_out_stream.next_in =
sshbuf_mutable_ptr(in)) == NULL)
return SSH_ERR_INTERNAL_ERROR;
ssh->state->compression_out_stream.avail_in = sshbuf_len(in);
/* Loop compressing until deflate() returns with avail_out != 0. */
do {
/* Set up fixed-size output buffer. */
ssh->state->compression_out_stream.next_out = buf;
ssh->state->compression_out_stream.avail_out = sizeof(buf);
/* Compress as much data into the buffer as possible. */
status = deflate(&ssh->state->compression_out_stream,
Z_PARTIAL_FLUSH);
switch (status) {
case Z_MEM_ERROR:
return SSH_ERR_ALLOC_FAIL;
case Z_OK:
/* Append compressed data to output_buffer. */
if ((r = sshbuf_put(out, buf, sizeof(buf) -
ssh->state->compression_out_stream.avail_out)) != 0)
return r;
break;
case Z_STREAM_ERROR:
default:
ssh->state->compression_out_failures++;
return SSH_ERR_INVALID_FORMAT;
}
} while (ssh->state->compression_out_stream.avail_out == 0);
return 0;
}
static int
uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out)
{
u_char buf[4096];
int r, status;
if (ssh->state->compression_in_started != 1)
return SSH_ERR_INTERNAL_ERROR;
if ((ssh->state->compression_in_stream.next_in =
sshbuf_mutable_ptr(in)) == NULL)
return SSH_ERR_INTERNAL_ERROR;
ssh->state->compression_in_stream.avail_in = sshbuf_len(in);
for (;;) {
/* Set up fixed-size output buffer. */
ssh->state->compression_in_stream.next_out = buf;
ssh->state->compression_in_stream.avail_out = sizeof(buf);
status = inflate(&ssh->state->compression_in_stream,
Z_PARTIAL_FLUSH);
switch (status) {
case Z_OK:
if ((r = sshbuf_put(out, buf, sizeof(buf) -
ssh->state->compression_in_stream.avail_out)) != 0)
return r;
break;
case Z_BUF_ERROR:
/*
* Comments in zlib.h say that we should keep calling
* inflate() until we get an error. This appears to
* be the error that we get.
*/
return 0;
case Z_DATA_ERROR:
return SSH_ERR_INVALID_FORMAT;
case Z_MEM_ERROR:
return SSH_ERR_ALLOC_FAIL;
case Z_STREAM_ERROR:
default:
ssh->state->compression_in_failures++;
return SSH_ERR_INTERNAL_ERROR;
}
}
/* NOTREACHED */
}
void
ssh_clear_newkeys(struct ssh *ssh, int mode)
{
if (ssh->kex && ssh->kex->newkeys[mode]) {
kex_free_newkeys(ssh->kex->newkeys[mode]);
ssh->kex->newkeys[mode] = NULL;
}
}
int
ssh_set_newkeys(struct ssh *ssh, int mode)
{
struct session_state *state = ssh->state;
struct sshenc *enc;
struct sshmac *mac;
struct sshcomp *comp;
struct sshcipher_ctx **ccp;
struct packet_state *ps;
u_int64_t *max_blocks;
const char *wmsg;
int r, crypt_type;
+ const char *dir = mode == MODE_OUT ? "out" : "in";
debug2("set_newkeys: mode %d", mode);
if (mode == MODE_OUT) {
ccp = &state->send_context;
crypt_type = CIPHER_ENCRYPT;
ps = &state->p_send;
max_blocks = &state->max_blocks_out;
} else {
ccp = &state->receive_context;
crypt_type = CIPHER_DECRYPT;
ps = &state->p_read;
max_blocks = &state->max_blocks_in;
}
if (state->newkeys[mode] != NULL) {
- debug("set_newkeys: rekeying, input %llu bytes %llu blocks, "
- "output %llu bytes %llu blocks",
+ debug("%s: rekeying %s, input %llu bytes %llu blocks, "
+ "output %llu bytes %llu blocks", __func__, dir,
(unsigned long long)state->p_read.bytes,
(unsigned long long)state->p_read.blocks,
(unsigned long long)state->p_send.bytes,
(unsigned long long)state->p_send.blocks);
- cipher_free(*ccp);
- *ccp = NULL;
kex_free_newkeys(state->newkeys[mode]);
state->newkeys[mode] = NULL;
}
/* note that both bytes and the seqnr are not reset */
ps->packets = ps->blocks = 0;
/* move newkeys from kex to state */
if ((state->newkeys[mode] = ssh->kex->newkeys[mode]) == NULL)
return SSH_ERR_INTERNAL_ERROR;
ssh->kex->newkeys[mode] = NULL;
enc = &state->newkeys[mode]->enc;
mac = &state->newkeys[mode]->mac;
comp = &state->newkeys[mode]->comp;
if (cipher_authlen(enc->cipher) == 0) {
if ((r = mac_init(mac)) != 0)
return r;
}
mac->enabled = 1;
- DBG(debug("cipher_init_context: %d", mode));
+ DBG(debug("%s: cipher_init_context: %s", __func__, dir));
+ cipher_free(*ccp);
+ *ccp = NULL;
if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->iv_len, crypt_type)) != 0)
return r;
if (!state->cipher_warning_done &&
(wmsg = cipher_warning_message(*ccp)) != NULL) {
error("Warning: %s", wmsg);
state->cipher_warning_done = 1;
}
/* Deleting the keys does not gain extra security */
/* explicit_bzero(enc->iv, enc->block_size);
explicit_bzero(enc->key, enc->key_len);
explicit_bzero(mac->key, mac->key_len); */
if ((comp->type == COMP_ZLIB ||
(comp->type == COMP_DELAYED &&
state->after_authentication)) && comp->enabled == 0) {
if ((r = ssh_packet_init_compression(ssh)) < 0)
return r;
if (mode == MODE_OUT) {
if ((r = start_compression_out(ssh, 6)) != 0)
return r;
} else {
if ((r = start_compression_in(ssh)) != 0)
return r;
}
comp->enabled = 1;
}
/*
* The 2^(blocksize*2) limit is too expensive for 3DES,
* so enforce a 1GB limit for small blocksizes.
* See RFC4344 section 3.2.
*/
if (enc->block_size >= 16)
*max_blocks = (u_int64_t)1 << (enc->block_size*2);
else
*max_blocks = ((u_int64_t)1 << 30) / enc->block_size;
if (state->rekey_limit)
*max_blocks = MINIMUM(*max_blocks,
state->rekey_limit / enc->block_size);
- debug("rekey after %llu blocks", (unsigned long long)*max_blocks);
+ debug("rekey %s after %llu blocks", dir,
+ (unsigned long long)*max_blocks);
return 0;
}
#define MAX_PACKETS (1U<<31)
static int
ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
{
struct session_state *state = ssh->state;
u_int32_t out_blocks;
/* XXX client can't cope with rekeying pre-auth */
if (!state->after_authentication)
return 0;
/* 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;
/* Peer can't rekey */
if (ssh->compat & SSH_BUG_NOREKEY)
return 0;
/*
* Permit one packet in or out per rekey - this allows us to
* make progress when rekey limits are very small.
*/
if (state->p_send.packets == 0 && state->p_read.packets == 0)
return 0;
/* Time-based rekeying */
if (state->rekey_interval != 0 &&
(int64_t)state->rekey_time + state->rekey_interval <= monotime())
return 1;
/*
* Always rekey when MAX_PACKETS sent in either direction
* As per RFC4344 section 3.1 we do this after 2^31 packets.
*/
if (state->p_send.packets > MAX_PACKETS ||
state->p_read.packets > MAX_PACKETS)
return 1;
/* Rekey after (cipher-specific) maximum blocks */
out_blocks = ROUNDUP(outbound_packet_len,
state->newkeys[MODE_OUT]->enc.block_size);
return (state->max_blocks_out &&
(state->p_send.blocks + out_blocks > state->max_blocks_out)) ||
(state->max_blocks_in &&
(state->p_read.blocks > state->max_blocks_in));
}
/*
* Delayed compression for SSH2 is enabled after authentication:
* This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
* and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received.
*/
static int
ssh_packet_enable_delayed_compress(struct ssh *ssh)
{
struct session_state *state = ssh->state;
struct sshcomp *comp = NULL;
int r, mode;
/*
* Remember that we are past the authentication step, so rekeying
* with COMP_DELAYED will turn on compression immediately.
*/
state->after_authentication = 1;
for (mode = 0; mode < MODE_MAX; mode++) {
/* protocol error: USERAUTH_SUCCESS received before NEWKEYS */
if (state->newkeys[mode] == NULL)
continue;
comp = &state->newkeys[mode]->comp;
if (comp && !comp->enabled && comp->type == COMP_DELAYED) {
if ((r = ssh_packet_init_compression(ssh)) != 0)
return r;
if (mode == MODE_OUT) {
if ((r = start_compression_out(ssh, 6)) != 0)
return r;
} else {
if ((r = start_compression_in(ssh)) != 0)
return r;
}
comp->enabled = 1;
}
}
return 0;
}
/* Used to mute debug logging for noisy packet types */
int
ssh_packet_log_type(u_char type)
{
switch (type) {
case SSH2_MSG_CHANNEL_DATA:
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
return 0;
default:
return 1;
}
}
/*
* Finalize packet in SSH2 format (compress, mac, encrypt, enqueue)
*/
int
ssh_packet_send2_wrapped(struct ssh *ssh)
{
struct session_state *state = ssh->state;
u_char type, *cp, macbuf[SSH_DIGEST_MAX_LENGTH];
u_char tmp, padlen, pad = 0;
u_int authlen = 0, aadlen = 0;
u_int len;
struct sshenc *enc = NULL;
struct sshmac *mac = NULL;
struct sshcomp *comp = NULL;
int r, block_size;
if (state->newkeys[MODE_OUT] != NULL) {
enc = &state->newkeys[MODE_OUT]->enc;
mac = &state->newkeys[MODE_OUT]->mac;
comp = &state->newkeys[MODE_OUT]->comp;
/* disable mac for authenticated encryption */
if ((authlen = cipher_authlen(enc->cipher)) != 0)
mac = NULL;
}
block_size = enc ? enc->block_size : 8;
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
type = (sshbuf_ptr(state->outgoing_packet))[5];
if (ssh_packet_log_type(type))
debug3("send packet: type %u", type);
#ifdef PACKET_DEBUG
fprintf(stderr, "plain: ");
sshbuf_dump(state->outgoing_packet, stderr);
#endif
if (comp && comp->enabled) {
len = sshbuf_len(state->outgoing_packet);
/* skip header, compress only payload */
if ((r = sshbuf_consume(state->outgoing_packet, 5)) != 0)
goto out;
sshbuf_reset(state->compression_buffer);
if ((r = compress_buffer(ssh, state->outgoing_packet,
state->compression_buffer)) != 0)
goto out;
sshbuf_reset(state->outgoing_packet);
if ((r = sshbuf_put(state->outgoing_packet,
"\0\0\0\0\0", 5)) != 0 ||
(r = sshbuf_putb(state->outgoing_packet,
state->compression_buffer)) != 0)
goto out;
DBG(debug("compression: raw %d compressed %zd", len,
sshbuf_len(state->outgoing_packet)));
}
/* sizeof (packet_len + pad_len + payload) */
len = sshbuf_len(state->outgoing_packet);
/*
* calc size of padding, alloc space, get random data,
* minimum padding is 4 bytes
*/
len -= aadlen; /* packet length is not encrypted for EtM modes */
padlen = block_size - (len % block_size);
if (padlen < 4)
padlen += block_size;
if (state->extra_pad) {
tmp = state->extra_pad;
state->extra_pad =
ROUNDUP(state->extra_pad, block_size);
/* check if roundup overflowed */
if (state->extra_pad < tmp)
return SSH_ERR_INVALID_ARGUMENT;
tmp = (len + padlen) % state->extra_pad;
/* Check whether pad calculation below will underflow */
if (tmp > state->extra_pad)
return SSH_ERR_INVALID_ARGUMENT;
pad = state->extra_pad - tmp;
DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
__func__, pad, len, padlen, state->extra_pad));
tmp = padlen;
padlen += pad;
/* Check whether padlen calculation overflowed */
if (padlen < tmp)
return SSH_ERR_INVALID_ARGUMENT; /* overflow */
state->extra_pad = 0;
}
if ((r = sshbuf_reserve(state->outgoing_packet, padlen, &cp)) != 0)
goto out;
if (enc && !cipher_ctx_is_plaintext(state->send_context)) {
/* random padding */
arc4random_buf(cp, padlen);
} else {
/* clear padding */
explicit_bzero(cp, padlen);
}
/* sizeof (packet_len + pad_len + payload + padding) */
len = sshbuf_len(state->outgoing_packet);
cp = sshbuf_mutable_ptr(state->outgoing_packet);
if (cp == NULL) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
}
/* packet_length includes payload, padding and padding length field */
POKE_U32(cp, len - 4);
cp[4] = padlen;
DBG(debug("send: len %d (includes padlen %d, aadlen %d)",
len, padlen, aadlen));
/* compute MAC over seqnr and packet(length fields, payload, padding) */
if (mac && mac->enabled && !mac->etm) {
if ((r = mac_compute(mac, state->p_send.seqnr,
sshbuf_ptr(state->outgoing_packet), len,
macbuf, sizeof(macbuf))) != 0)
goto out;
DBG(debug("done calc MAC out #%d", state->p_send.seqnr));
}
/* encrypt packet and append to output buffer. */
if ((r = sshbuf_reserve(state->output,
sshbuf_len(state->outgoing_packet) + authlen, &cp)) != 0)
goto out;
if ((r = cipher_crypt(state->send_context, state->p_send.seqnr, cp,
sshbuf_ptr(state->outgoing_packet),
len - aadlen, aadlen, authlen)) != 0)
goto out;
/* append unencrypted MAC */
if (mac && mac->enabled) {
if (mac->etm) {
/* EtM: compute mac over aadlen + cipher text */
if ((r = mac_compute(mac, state->p_send.seqnr,
cp, len, macbuf, sizeof(macbuf))) != 0)
goto out;
DBG(debug("done calc MAC(EtM) out #%d",
state->p_send.seqnr));
}
if ((r = sshbuf_put(state->output, macbuf, mac->mac_len)) != 0)
goto out;
}
#ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: ");
sshbuf_dump(state->output, stderr);
#endif
/* increment sequence number for outgoing packets */
if (++state->p_send.seqnr == 0)
logit("outgoing seqnr wraps around");
if (++state->p_send.packets == 0)
if (!(ssh->compat & SSH_BUG_NOREKEY))
return SSH_ERR_NEED_REKEY;
state->p_send.blocks += len / block_size;
state->p_send.bytes += len;
sshbuf_reset(state->outgoing_packet);
if (type == SSH2_MSG_NEWKEYS)
r = ssh_set_newkeys(ssh, MODE_OUT);
else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
r = ssh_packet_enable_delayed_compress(ssh);
else
r = 0;
out:
return r;
}
/* returns non-zero if the specified packet type is usec by KEX */
static int
ssh_packet_type_is_kex(u_char type)
{
return
type >= SSH2_MSG_TRANSPORT_MIN &&
type <= SSH2_MSG_TRANSPORT_MAX &&
type != SSH2_MSG_SERVICE_REQUEST &&
type != SSH2_MSG_SERVICE_ACCEPT &&
type != SSH2_MSG_EXT_INFO;
}
int
ssh_packet_send2(struct ssh *ssh)
{
struct session_state *state = ssh->state;
struct packet *p;
u_char type;
int r, need_rekey;
if (sshbuf_len(state->outgoing_packet) < 6)
return SSH_ERR_INTERNAL_ERROR;
type = sshbuf_ptr(state->outgoing_packet)[5];
need_rekey = !ssh_packet_type_is_kex(type) &&
ssh_packet_need_rekeying(ssh, sshbuf_len(state->outgoing_packet));
/*
* During rekeying we can only send key exchange messages.
* Queue everything else.
*/
if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) {
if (need_rekey)
debug3("%s: rekex triggered", __func__);
debug("enqueue packet: %u", type);
p = calloc(1, sizeof(*p));
if (p == NULL)
return SSH_ERR_ALLOC_FAIL;
p->type = type;
p->payload = state->outgoing_packet;
TAILQ_INSERT_TAIL(&state->outgoing, p, next);
state->outgoing_packet = sshbuf_new();
if (state->outgoing_packet == NULL)
return SSH_ERR_ALLOC_FAIL;
if (need_rekey) {
/*
* This packet triggered a rekey, so send the
* KEXINIT now.
* NB. reenters this function via kex_start_rekex().
*/
return kex_start_rekex(ssh);
}
return 0;
}
/* rekeying starts with sending KEXINIT */
if (type == SSH2_MSG_KEXINIT)
state->rekeying = 1;
if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
return r;
/* after a NEWKEYS message we can send the complete queue */
if (type == SSH2_MSG_NEWKEYS) {
state->rekeying = 0;
state->rekey_time = monotime();
while ((p = TAILQ_FIRST(&state->outgoing))) {
type = p->type;
/*
* If this packet triggers a rekex, then skip the
* remaining packets in the queue for now.
* NB. re-enters this function via kex_start_rekex.
*/
if (ssh_packet_need_rekeying(ssh,
sshbuf_len(p->payload))) {
debug3("%s: queued packet triggered rekex",
__func__);
return kex_start_rekex(ssh);
}
debug("dequeue packet: %u", type);
sshbuf_free(state->outgoing_packet);
state->outgoing_packet = p->payload;
TAILQ_REMOVE(&state->outgoing, p, next);
memset(p, 0, sizeof(*p));
free(p);
if ((r = ssh_packet_send2_wrapped(ssh)) != 0)
return r;
}
}
return 0;
}
/*
* Waits until a packet has been received, and returns its type. Note that
* no other data is processed until this returns, so this function should not
* be used during the interactive session.
*/
int
ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
int len, r, ms_remain;
fd_set *setp;
char buf[8192];
struct timeval timeout, start, *timeoutp = NULL;
DBG(debug("packet_read()"));
setp = calloc(howmany(state->connection_in + 1,
NFDBITS), sizeof(fd_mask));
if (setp == NULL)
return SSH_ERR_ALLOC_FAIL;
/*
* Since we are blocking, ensure that all written packets have
* been sent.
*/
if ((r = ssh_packet_write_wait(ssh)) != 0)
goto out;
/* Stay in the loop until we have received a complete packet. */
for (;;) {
/* Try to read a packet from the buffer. */
r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
if (r != 0)
break;
/* If we got a packet, return it. */
if (*typep != SSH_MSG_NONE)
break;
/*
* Otherwise, wait for some data to arrive, add it to the
* buffer, and try again.
*/
memset(setp, 0, howmany(state->connection_in + 1,
NFDBITS) * sizeof(fd_mask));
FD_SET(state->connection_in, setp);
if (state->packet_timeout_ms > 0) {
ms_remain = state->packet_timeout_ms;
timeoutp = &timeout;
}
/* Wait for some data to arrive. */
for (;;) {
if (state->packet_timeout_ms != -1) {
ms_to_timeval(&timeout, ms_remain);
monotime_tv(&start);
}
if ((r = select(state->connection_in + 1, setp,
NULL, NULL, timeoutp)) >= 0)
break;
if (errno != EAGAIN && errno != EINTR &&
errno != EWOULDBLOCK) {
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
if (state->packet_timeout_ms == -1)
continue;
ms_subtract_diff(&start, &ms_remain);
if (ms_remain <= 0) {
r = 0;
break;
}
}
if (r == 0) {
r = SSH_ERR_CONN_TIMEOUT;
goto out;
}
/* Read data from the socket. */
len = read(state->connection_in, buf, sizeof(buf));
if (len == 0) {
r = SSH_ERR_CONN_CLOSED;
goto out;
}
if (len < 0) {
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
/* Append it to the buffer. */
if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
goto out;
}
out:
free(setp);
return r;
}
int
ssh_packet_read(struct ssh *ssh)
{
u_char type;
int r;
if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
return type;
}
/*
* Waits until a packet has been received, verifies that its type matches
* that given, and gives a fatal error and exits if there is a mismatch.
*/
int
ssh_packet_read_expect(struct ssh *ssh, u_int expected_type)
{
int r;
u_char type;
if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
return r;
if (type != expected_type) {
if ((r = sshpkt_disconnect(ssh,
"Protocol error: expected packet type %d, got %d",
expected_type, type)) != 0)
return r;
return SSH_ERR_PROTOCOL_ERROR;
}
return 0;
}
static int
ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
const u_char *cp;
size_t need;
int r;
if (ssh->kex)
return SSH_ERR_INTERNAL_ERROR;
*typep = SSH_MSG_NONE;
cp = sshbuf_ptr(state->input);
if (state->packlen == 0) {
if (sshbuf_len(state->input) < 4 + 1)
return 0; /* packet is incomplete */
state->packlen = PEEK_U32(cp);
if (state->packlen < 4 + 1 ||
state->packlen > PACKET_MAX_SIZE)
return SSH_ERR_MESSAGE_INCOMPLETE;
}
need = state->packlen + 4;
if (sshbuf_len(state->input) < need)
return 0; /* packet is incomplete */
sshbuf_reset(state->incoming_packet);
if ((r = sshbuf_put(state->incoming_packet, cp + 4,
state->packlen)) != 0 ||
(r = sshbuf_consume(state->input, need)) != 0 ||
(r = sshbuf_get_u8(state->incoming_packet, NULL)) != 0 ||
(r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
return r;
if (ssh_packet_log_type(*typep))
debug3("%s: type %u", __func__, *typep);
/* sshbuf_dump(state->incoming_packet, stderr); */
/* reset for next packet */
state->packlen = 0;
return r;
}
int
ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
u_int padlen, need;
u_char *cp;
u_int maclen, aadlen = 0, authlen = 0, block_size;
struct sshenc *enc = NULL;
struct sshmac *mac = NULL;
struct sshcomp *comp = NULL;
int r;
if (state->mux)
return ssh_packet_read_poll2_mux(ssh, typep, seqnr_p);
*typep = SSH_MSG_NONE;
if (state->packet_discard)
return 0;
if (state->newkeys[MODE_IN] != NULL) {
enc = &state->newkeys[MODE_IN]->enc;
mac = &state->newkeys[MODE_IN]->mac;
comp = &state->newkeys[MODE_IN]->comp;
/* disable mac for authenticated encryption */
if ((authlen = cipher_authlen(enc->cipher)) != 0)
mac = NULL;
}
maclen = mac && mac->enabled ? mac->mac_len : 0;
block_size = enc ? enc->block_size : 8;
aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
if (aadlen && state->packlen == 0) {
if (cipher_get_length(state->receive_context,
&state->packlen, state->p_read.seqnr,
sshbuf_ptr(state->input), sshbuf_len(state->input)) != 0)
return 0;
if (state->packlen < 1 + 4 ||
state->packlen > PACKET_MAX_SIZE) {
#ifdef PACKET_DEBUG
sshbuf_dump(state->input, stderr);
#endif
logit("Bad packet length %u.", state->packlen);
if ((r = sshpkt_disconnect(ssh, "Packet corrupt")) != 0)
return r;
return SSH_ERR_CONN_CORRUPT;
}
sshbuf_reset(state->incoming_packet);
} else if (state->packlen == 0) {
/*
* check if input size is less than the cipher block size,
* decrypt first block and extract length of incoming packet
*/
if (sshbuf_len(state->input) < block_size)
return 0;
sshbuf_reset(state->incoming_packet);
if ((r = sshbuf_reserve(state->incoming_packet, block_size,
&cp)) != 0)
goto out;
if ((r = cipher_crypt(state->receive_context,
state->p_send.seqnr, cp, sshbuf_ptr(state->input),
block_size, 0, 0)) != 0)
goto out;
state->packlen = PEEK_U32(sshbuf_ptr(state->incoming_packet));
if (state->packlen < 1 + 4 ||
state->packlen > PACKET_MAX_SIZE) {
#ifdef PACKET_DEBUG
fprintf(stderr, "input: \n");
sshbuf_dump(state->input, stderr);
fprintf(stderr, "incoming_packet: \n");
sshbuf_dump(state->incoming_packet, stderr);
#endif
logit("Bad packet length %u.", state->packlen);
return ssh_packet_start_discard(ssh, enc, mac, 0,
PACKET_MAX_SIZE);
}
if ((r = sshbuf_consume(state->input, block_size)) != 0)
goto out;
}
DBG(debug("input: packet len %u", state->packlen+4));
if (aadlen) {
/* only the payload is encrypted */
need = state->packlen;
} else {
/*
* the payload size and the payload are encrypted, but we
* have a partial packet of block_size bytes
*/
need = 4 + state->packlen - block_size;
}
DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d,"
" aadlen %d", block_size, need, maclen, authlen, aadlen));
if (need % block_size != 0) {
logit("padding error: need %d block %d mod %d",
need, block_size, need % block_size);
return ssh_packet_start_discard(ssh, enc, mac, 0,
PACKET_MAX_SIZE - block_size);
}
/*
* check if the entire packet has been received and
* decrypt into incoming_packet:
* 'aadlen' bytes are unencrypted, but authenticated.
* 'need' bytes are encrypted, followed by either
* 'authlen' bytes of authentication tag or
* 'maclen' bytes of message authentication code.
*/
if (sshbuf_len(state->input) < aadlen + need + authlen + maclen)
return 0; /* packet is incomplete */
#ifdef PACKET_DEBUG
fprintf(stderr, "read_poll enc/full: ");
sshbuf_dump(state->input, stderr);
#endif
/* EtM: check mac over encrypted input */
if (mac && mac->enabled && mac->etm) {
if ((r = mac_check(mac, state->p_read.seqnr,
sshbuf_ptr(state->input), aadlen + need,
sshbuf_ptr(state->input) + aadlen + need + authlen,
maclen)) != 0) {
if (r == SSH_ERR_MAC_INVALID)
logit("Corrupted MAC on input.");
goto out;
}
}
if ((r = sshbuf_reserve(state->incoming_packet, aadlen + need,
&cp)) != 0)
goto out;
if ((r = cipher_crypt(state->receive_context, state->p_read.seqnr, cp,
sshbuf_ptr(state->input), need, aadlen, authlen)) != 0)
goto out;
if ((r = sshbuf_consume(state->input, aadlen + need + authlen)) != 0)
goto out;
if (mac && mac->enabled) {
/* Not EtM: check MAC over cleartext */
if (!mac->etm && (r = mac_check(mac, state->p_read.seqnr,
sshbuf_ptr(state->incoming_packet),
sshbuf_len(state->incoming_packet),
sshbuf_ptr(state->input), maclen)) != 0) {
if (r != SSH_ERR_MAC_INVALID)
goto out;
logit("Corrupted MAC on input.");
if (need + block_size > PACKET_MAX_SIZE)
return SSH_ERR_INTERNAL_ERROR;
return ssh_packet_start_discard(ssh, enc, mac,
sshbuf_len(state->incoming_packet),
PACKET_MAX_SIZE - need - block_size);
}
/* Remove MAC from input buffer */
DBG(debug("MAC #%d ok", state->p_read.seqnr));
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
goto out;
}
if (seqnr_p != NULL)
*seqnr_p = state->p_read.seqnr;
if (++state->p_read.seqnr == 0)
logit("incoming seqnr wraps around");
if (++state->p_read.packets == 0)
if (!(ssh->compat & SSH_BUG_NOREKEY))
return SSH_ERR_NEED_REKEY;
state->p_read.blocks += (state->packlen + 4) / block_size;
state->p_read.bytes += state->packlen + 4;
/* get padlen */
padlen = sshbuf_ptr(state->incoming_packet)[4];
DBG(debug("input: padlen %d", padlen));
if (padlen < 4) {
if ((r = sshpkt_disconnect(ssh,
"Corrupted padlen %d on input.", padlen)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
return r;
return SSH_ERR_CONN_CORRUPT;
}
/* skip packet size + padlen, discard padding */
if ((r = sshbuf_consume(state->incoming_packet, 4 + 1)) != 0 ||
((r = sshbuf_consume_end(state->incoming_packet, padlen)) != 0))
goto out;
DBG(debug("input: len before de-compress %zd",
sshbuf_len(state->incoming_packet)));
if (comp && comp->enabled) {
sshbuf_reset(state->compression_buffer);
if ((r = uncompress_buffer(ssh, state->incoming_packet,
state->compression_buffer)) != 0)
goto out;
sshbuf_reset(state->incoming_packet);
if ((r = sshbuf_putb(state->incoming_packet,
state->compression_buffer)) != 0)
goto out;
DBG(debug("input: len after de-compress %zd",
sshbuf_len(state->incoming_packet)));
}
/*
* get packet type, implies consume.
* return length of payload (without type field)
*/
if ((r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
goto out;
if (ssh_packet_log_type(*typep))
debug3("receive packet: type %u", *typep);
if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
if ((r = sshpkt_disconnect(ssh,
"Invalid ssh2 packet type: %d", *typep)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
return r;
return SSH_ERR_PROTOCOL_ERROR;
}
if (state->hook_in != NULL &&
(r = state->hook_in(ssh, state->incoming_packet, typep,
state->hook_in_ctx)) != 0)
return r;
if (*typep == SSH2_MSG_USERAUTH_SUCCESS && !state->server_side)
r = ssh_packet_enable_delayed_compress(ssh);
else
r = 0;
#ifdef PACKET_DEBUG
fprintf(stderr, "read/plain[%d]:\r\n", *typep);
sshbuf_dump(state->incoming_packet, stderr);
#endif
/* reset for next packet */
state->packlen = 0;
/* do we need to rekey? */
if (ssh_packet_need_rekeying(ssh, 0)) {
debug3("%s: rekex triggered", __func__);
if ((r = kex_start_rekex(ssh)) != 0)
return r;
}
out:
return r;
}
int
ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
{
struct session_state *state = ssh->state;
u_int reason, seqnr;
int r;
u_char *msg;
for (;;) {
msg = NULL;
r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
if (r != 0)
return r;
if (*typep) {
state->keep_alive_timeouts = 0;
DBG(debug("received packet type %d", *typep));
}
switch (*typep) {
case SSH2_MSG_IGNORE:
debug3("Received SSH2_MSG_IGNORE");
break;
case SSH2_MSG_DEBUG:
if ((r = sshpkt_get_u8(ssh, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
free(msg);
return r;
}
debug("Remote: %.900s", msg);
free(msg);
break;
case SSH2_MSG_DISCONNECT:
if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
(r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
return r;
/* Ignore normal client exit notifications */
do_log2(ssh->state->server_side &&
reason == SSH2_DISCONNECT_BY_APPLICATION ?
SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
"Received disconnect from %s port %d:"
"%u: %.400s", ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh), reason, msg);
free(msg);
return SSH_ERR_DISCONNECTED;
case SSH2_MSG_UNIMPLEMENTED:
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
return r;
debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
seqnr);
break;
default:
return 0;
}
}
}
/*
* Buffers the given amount of input characters. This is intended to be used
* together with packet_read_poll.
*/
int
ssh_packet_process_incoming(struct ssh *ssh, const char *buf, u_int len)
{
struct session_state *state = ssh->state;
int r;
if (state->packet_discard) {
state->keep_alive_timeouts = 0; /* ?? */
if (len >= state->packet_discard) {
if ((r = ssh_packet_stop_discard(ssh)) != 0)
return r;
}
state->packet_discard -= len;
return 0;
}
if ((r = sshbuf_put(ssh->state->input, buf, len)) != 0)
return r;
return 0;
}
int
ssh_packet_remaining(struct ssh *ssh)
{
return sshbuf_len(ssh->state->incoming_packet);
}
/*
* Sends a diagnostic message from the server to the client. This message
* can be sent at any time (but not while constructing another message). The
* message is printed immediately, but only if the client is being executed
* in verbose mode. These messages are primarily intended to ease debugging
* authentication problems. The length of the formatted message must not
* exceed 1024 bytes. This will automatically call ssh_packet_write_wait.
*/
void
ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
{
char buf[1024];
va_list args;
int r;
if ((ssh->compat & SSH_BUG_DEBUG))
return;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
debug3("sending debug message: %s", buf);
if ((r = sshpkt_start(ssh, SSH2_MSG_DEBUG)) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* always display */
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
}
void
sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l)
{
snprintf(s, l, "%.200s%s%s port %d",
ssh->log_preamble ? ssh->log_preamble : "",
ssh->log_preamble ? " " : "",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
}
/*
* Pretty-print connection-terminating errors and exit.
*/
-void
-sshpkt_fatal(struct ssh *ssh, const char *tag, int r)
+static void
+sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap)
{
- char remote_id[512];
+ char *tag = NULL, remote_id[512];
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
switch (r) {
case SSH_ERR_CONN_CLOSED:
ssh_packet_clear_keys(ssh);
logdie("Connection closed by %s", remote_id);
case SSH_ERR_CONN_TIMEOUT:
ssh_packet_clear_keys(ssh);
logdie("Connection %s %s timed out",
ssh->state->server_side ? "from" : "to", remote_id);
case SSH_ERR_DISCONNECTED:
ssh_packet_clear_keys(ssh);
logdie("Disconnected from %s", remote_id);
case SSH_ERR_SYSTEM_ERROR:
if (errno == ECONNRESET) {
ssh_packet_clear_keys(ssh);
logdie("Connection reset by %s", remote_id);
}
/* FALLTHROUGH */
case SSH_ERR_NO_CIPHER_ALG_MATCH:
case SSH_ERR_NO_MAC_ALG_MATCH:
case SSH_ERR_NO_COMPRESS_ALG_MATCH:
case SSH_ERR_NO_KEX_ALG_MATCH:
case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
if (ssh && ssh->kex && ssh->kex->failed_choice) {
ssh_packet_clear_keys(ssh);
logdie("Unable to negotiate with %s: %s. "
"Their offer: %s", remote_id, ssh_err(r),
ssh->kex->failed_choice);
}
/* FALLTHROUGH */
default:
+ if (vasprintf(&tag, fmt, ap) == -1) {
+ ssh_packet_clear_keys(ssh);
+ logdie("%s: could not allocate failure message",
+ __func__);
+ }
ssh_packet_clear_keys(ssh);
logdie("%s%sConnection %s %s: %s",
tag != NULL ? tag : "", tag != NULL ? ": " : "",
ssh->state->server_side ? "from" : "to",
remote_id, ssh_err(r));
}
}
+void
+sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ sshpkt_vfatal(ssh, r, fmt, ap);
+ /* NOTREACHED */
+ va_end(ap);
+ logdie("%s: should have exited", __func__);
+}
+
/*
* Logs the error plus constructs and sends a disconnect packet, closes the
* connection, and exits. This function never returns. The error message
* should not contain a newline. The length of the formatted message must
* not exceed 1024 bytes.
*/
void
ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...)
{
char buf[1024], remote_id[512];
va_list args;
static int disconnecting = 0;
int r;
if (disconnecting) /* Guard against recursive invocations. */
fatal("packet_disconnect called recursively.");
disconnecting = 1;
/*
* Format the message. Note that the caller must make sure the
* message is of limited size.
*/
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
/* Display the error locally */
logit("Disconnecting %s: %.100s", remote_id, buf);
/*
* Send the disconnect message to the other side, and wait
* for it to get sent.
*/
if ((r = sshpkt_disconnect(ssh, "%s", buf)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
if ((r = ssh_packet_write_wait(ssh)) != 0)
- sshpkt_fatal(ssh, __func__, r);
+ sshpkt_fatal(ssh, r, "%s", __func__);
/* Close the connection. */
ssh_packet_close(ssh);
cleanup_exit(255);
}
/*
* Checks if there is any buffered output, and tries to write some of
* the output.
*/
int
ssh_packet_write_poll(struct ssh *ssh)
{
struct session_state *state = ssh->state;
int len = sshbuf_len(state->output);
int r;
if (len > 0) {
len = write(state->connection_out,
sshbuf_ptr(state->output), len);
if (len == -1) {
if (errno == EINTR || errno == EAGAIN ||
errno == EWOULDBLOCK)
return 0;
return SSH_ERR_SYSTEM_ERROR;
}
if (len == 0)
return SSH_ERR_CONN_CLOSED;
if ((r = sshbuf_consume(state->output, len)) != 0)
return r;
}
return 0;
}
/*
* Calls packet_write_poll repeatedly until all pending output data has been
* written.
*/
int
ssh_packet_write_wait(struct ssh *ssh)
{
fd_set *setp;
int ret, r, ms_remain = 0;
struct timeval start, timeout, *timeoutp = NULL;
struct session_state *state = ssh->state;
setp = calloc(howmany(state->connection_out + 1,
NFDBITS), sizeof(fd_mask));
if (setp == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = ssh_packet_write_poll(ssh)) != 0) {
free(setp);
return r;
}
while (ssh_packet_have_data_to_write(ssh)) {
memset(setp, 0, howmany(state->connection_out + 1,
NFDBITS) * sizeof(fd_mask));
FD_SET(state->connection_out, setp);
if (state->packet_timeout_ms > 0) {
ms_remain = state->packet_timeout_ms;
timeoutp = &timeout;
}
for (;;) {
if (state->packet_timeout_ms != -1) {
ms_to_timeval(&timeout, ms_remain);
monotime_tv(&start);
}
if ((ret = select(state->connection_out + 1,
NULL, setp, NULL, timeoutp)) >= 0)
break;
if (errno != EAGAIN && errno != EINTR &&
errno != EWOULDBLOCK)
break;
if (state->packet_timeout_ms == -1)
continue;
ms_subtract_diff(&start, &ms_remain);
if (ms_remain <= 0) {
ret = 0;
break;
}
}
if (ret == 0) {
free(setp);
return SSH_ERR_CONN_TIMEOUT;
}
if ((r = ssh_packet_write_poll(ssh)) != 0) {
free(setp);
return r;
}
}
free(setp);
return 0;
}
/* Returns true if there is buffered data to write to the connection. */
int
ssh_packet_have_data_to_write(struct ssh *ssh)
{
return sshbuf_len(ssh->state->output) != 0;
}
/* Returns true if there is not too much data to write to the connection. */
int
ssh_packet_not_very_much_data_to_write(struct ssh *ssh)
{
if (ssh->state->interactive_mode)
return sshbuf_len(ssh->state->output) < 16384;
else
return sshbuf_len(ssh->state->output) < 128 * 1024;
}
void
ssh_packet_set_tos(struct ssh *ssh, int tos)
{
#ifndef IP_TOS_IS_BROKEN
if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX)
return;
switch (ssh_packet_connection_af(ssh)) {
# ifdef IP_TOS
case AF_INET:
debug3("%s: set IP_TOS 0x%02x", __func__, tos);
if (setsockopt(ssh->state->connection_in,
IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
error("setsockopt IP_TOS %d: %.100s:",
tos, strerror(errno));
break;
# endif /* IP_TOS */
# ifdef IPV6_TCLASS
case AF_INET6:
debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos);
if (setsockopt(ssh->state->connection_in,
IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
error("setsockopt IPV6_TCLASS %d: %.100s:",
tos, strerror(errno));
break;
# endif /* IPV6_TCLASS */
}
#endif /* IP_TOS_IS_BROKEN */
}
/* Informs that the current session is interactive. Sets IP flags for that. */
void
ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk)
{
struct session_state *state = ssh->state;
if (state->set_interactive_called)
return;
state->set_interactive_called = 1;
/* Record that we are in interactive mode. */
state->interactive_mode = interactive;
/* Only set socket options if using a socket. */
if (!ssh_packet_connection_is_on_socket(ssh))
return;
set_nodelay(state->connection_in);
ssh_packet_set_tos(ssh, interactive ? qos_interactive :
qos_bulk);
}
/* Returns true if the current connection is interactive. */
int
ssh_packet_is_interactive(struct ssh *ssh)
{
return ssh->state->interactive_mode;
}
int
ssh_packet_set_maxsize(struct ssh *ssh, u_int s)
{
struct session_state *state = ssh->state;
if (state->set_maxsize_called) {
logit("packet_set_maxsize: called twice: old %d new %d",
state->max_packet_size, s);
return -1;
}
if (s < 4 * 1024 || s > 1024 * 1024) {
logit("packet_set_maxsize: bad size %d", s);
return -1;
}
state->set_maxsize_called = 1;
debug("packet_set_maxsize: setting to %d", s);
state->max_packet_size = s;
return s;
}
int
ssh_packet_inc_alive_timeouts(struct ssh *ssh)
{
return ++ssh->state->keep_alive_timeouts;
}
void
ssh_packet_set_alive_timeouts(struct ssh *ssh, int ka)
{
ssh->state->keep_alive_timeouts = ka;
}
u_int
ssh_packet_get_maxsize(struct ssh *ssh)
{
return ssh->state->max_packet_size;
}
void
ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds)
{
debug3("rekey after %llu bytes, %u seconds", (unsigned long long)bytes,
(unsigned int)seconds);
ssh->state->rekey_limit = bytes;
ssh->state->rekey_interval = seconds;
}
time_t
ssh_packet_get_rekey_timeout(struct ssh *ssh)
{
time_t seconds;
seconds = ssh->state->rekey_time + ssh->state->rekey_interval -
monotime();
return (seconds <= 0 ? 1 : seconds);
}
void
ssh_packet_set_server(struct ssh *ssh)
{
ssh->state->server_side = 1;
+ ssh->kex->server = 1; /* XXX unify? */
}
void
ssh_packet_set_authenticated(struct ssh *ssh)
{
ssh->state->after_authentication = 1;
}
void *
ssh_packet_get_input(struct ssh *ssh)
{
return (void *)ssh->state->input;
}
void *
ssh_packet_get_output(struct ssh *ssh)
{
return (void *)ssh->state->output;
}
/* Reset after_authentication and reset compression in post-auth privsep */
static int
ssh_packet_set_postauth(struct ssh *ssh)
{
int r;
debug("%s: called", __func__);
/* This was set in net child, but is not visible in user child */
ssh->state->after_authentication = 1;
ssh->state->rekeying = 0;
if ((r = ssh_packet_enable_delayed_compress(ssh)) != 0)
return r;
return 0;
}
/* Packet state (de-)serialization for privsep */
/* turn kex into a blob for packet state serialization */
static int
kex_to_blob(struct sshbuf *m, struct kex *kex)
{
int r;
if ((r = sshbuf_put_string(m, kex->session_id,
kex->session_id_len)) != 0 ||
(r = sshbuf_put_u32(m, kex->we_need)) != 0 ||
(r = sshbuf_put_cstring(m, kex->hostkey_alg)) != 0 ||
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
(r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
- (r = sshbuf_put_u32(m, kex->flags)) != 0 ||
- (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 ||
- (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0)
+ (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
+ (r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->flags)) != 0)
return r;
return 0;
}
/* turn key exchange results into a blob for packet state serialization */
static int
newkeys_to_blob(struct sshbuf *m, struct ssh *ssh, int mode)
{
struct sshbuf *b;
struct sshcipher_ctx *cc;
struct sshcomp *comp;
struct sshenc *enc;
struct sshmac *mac;
struct newkeys *newkey;
int r;
if ((newkey = ssh->state->newkeys[mode]) == NULL)
return SSH_ERR_INTERNAL_ERROR;
enc = &newkey->enc;
mac = &newkey->mac;
comp = &newkey->comp;
cc = (mode == MODE_OUT) ? ssh->state->send_context :
ssh->state->receive_context;
if ((r = cipher_get_keyiv(cc, enc->iv, enc->iv_len)) != 0)
return r;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_cstring(b, enc->name)) != 0 ||
(r = sshbuf_put_u32(b, enc->enabled)) != 0 ||
(r = sshbuf_put_u32(b, enc->block_size)) != 0 ||
(r = sshbuf_put_string(b, enc->key, enc->key_len)) != 0 ||
(r = sshbuf_put_string(b, enc->iv, enc->iv_len)) != 0)
goto out;
if (cipher_authlen(enc->cipher) == 0) {
if ((r = sshbuf_put_cstring(b, mac->name)) != 0 ||
(r = sshbuf_put_u32(b, mac->enabled)) != 0 ||
(r = sshbuf_put_string(b, mac->key, mac->key_len)) != 0)
goto out;
}
if ((r = sshbuf_put_u32(b, comp->type)) != 0 ||
(r = sshbuf_put_cstring(b, comp->name)) != 0)
goto out;
r = sshbuf_put_stringb(m, b);
out:
sshbuf_free(b);
return r;
}
/* serialize packet state into a blob */
int
ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m)
{
struct session_state *state = ssh->state;
int r;
if ((r = kex_to_blob(m, ssh->kex)) != 0 ||
(r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 ||
(r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 ||
(r = sshbuf_put_u64(m, state->rekey_limit)) != 0 ||
(r = sshbuf_put_u32(m, state->rekey_interval)) != 0 ||
(r = sshbuf_put_u32(m, state->p_send.seqnr)) != 0 ||
(r = sshbuf_put_u64(m, state->p_send.blocks)) != 0 ||
(r = sshbuf_put_u32(m, state->p_send.packets)) != 0 ||
(r = sshbuf_put_u64(m, state->p_send.bytes)) != 0 ||
(r = sshbuf_put_u32(m, state->p_read.seqnr)) != 0 ||
(r = sshbuf_put_u64(m, state->p_read.blocks)) != 0 ||
(r = sshbuf_put_u32(m, state->p_read.packets)) != 0 ||
(r = sshbuf_put_u64(m, state->p_read.bytes)) != 0 ||
(r = sshbuf_put_stringb(m, state->input)) != 0 ||
(r = sshbuf_put_stringb(m, state->output)) != 0)
return r;
return 0;
}
/* restore key exchange results from blob for packet state de-serialization */
static int
newkeys_from_blob(struct sshbuf *m, struct ssh *ssh, int mode)
{
struct sshbuf *b = NULL;
struct sshcomp *comp;
struct sshenc *enc;
struct sshmac *mac;
struct newkeys *newkey = NULL;
size_t keylen, ivlen, maclen;
int r;
if ((newkey = calloc(1, sizeof(*newkey))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_froms(m, &b)) != 0)
goto out;
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
enc = &newkey->enc;
mac = &newkey->mac;
comp = &newkey->comp;
if ((r = sshbuf_get_cstring(b, &enc->name, NULL)) != 0 ||
(r = sshbuf_get_u32(b, (u_int *)&enc->enabled)) != 0 ||
(r = sshbuf_get_u32(b, &enc->block_size)) != 0 ||
(r = sshbuf_get_string(b, &enc->key, &keylen)) != 0 ||
(r = sshbuf_get_string(b, &enc->iv, &ivlen)) != 0)
goto out;
if ((enc->cipher = cipher_by_name(enc->name)) == NULL) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (cipher_authlen(enc->cipher) == 0) {
if ((r = sshbuf_get_cstring(b, &mac->name, NULL)) != 0)
goto out;
if ((r = mac_setup(mac, mac->name)) != 0)
goto out;
if ((r = sshbuf_get_u32(b, (u_int *)&mac->enabled)) != 0 ||
(r = sshbuf_get_string(b, &mac->key, &maclen)) != 0)
goto out;
if (maclen > mac->key_len) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
mac->key_len = maclen;
}
if ((r = sshbuf_get_u32(b, &comp->type)) != 0 ||
(r = sshbuf_get_cstring(b, &comp->name, NULL)) != 0)
goto out;
if (sshbuf_len(b) != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
enc->key_len = keylen;
enc->iv_len = ivlen;
ssh->kex->newkeys[mode] = newkey;
newkey = NULL;
r = 0;
out:
free(newkey);
sshbuf_free(b);
return r;
}
/* restore kex from blob for packet state de-serialization */
static int
kex_from_blob(struct sshbuf *m, struct kex **kexp)
{
struct kex *kex;
int r;
- if ((kex = calloc(1, sizeof(struct kex))) == NULL ||
- (kex->my = sshbuf_new()) == NULL ||
- (kex->peer = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
+ if ((kex = kex_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
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_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
- (r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
- (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 ||
- (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0)
+ (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
+ (r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->flags)) != 0)
goto out;
kex->server = 1;
kex->done = 1;
r = 0;
out:
if (r != 0 || kexp == NULL) {
- if (kex != NULL) {
- sshbuf_free(kex->my);
- sshbuf_free(kex->peer);
- free(kex);
- }
+ kex_free(kex);
if (kexp != NULL)
*kexp = NULL;
} else {
+ kex_free(*kexp);
*kexp = kex;
}
return r;
}
/*
* Restore packet state from content of blob 'm' (de-serialization).
* Note that 'm' will be partially consumed on parsing or any other errors.
*/
int
ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
{
struct session_state *state = ssh->state;
const u_char *input, *output;
size_t ilen, olen;
int r;
if ((r = kex_from_blob(m, &ssh->kex)) != 0 ||
(r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 ||
(r = newkeys_from_blob(m, ssh, MODE_IN)) != 0 ||
(r = sshbuf_get_u64(m, &state->rekey_limit)) != 0 ||
(r = sshbuf_get_u32(m, &state->rekey_interval)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_send.seqnr)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_send.blocks)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_send.packets)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_send.bytes)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_read.seqnr)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_read.blocks)) != 0 ||
(r = sshbuf_get_u32(m, &state->p_read.packets)) != 0 ||
(r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
return r;
/*
* We set the time here so that in post-auth privsep slave we
* count from the completion of the authentication.
*/
state->rekey_time = monotime();
/* XXX ssh_set_newkeys overrides p_read.packets? XXX */
if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0 ||
(r = ssh_set_newkeys(ssh, MODE_OUT)) != 0)
return r;
if ((r = ssh_packet_set_postauth(ssh)) != 0)
return r;
sshbuf_reset(state->input);
sshbuf_reset(state->output);
if ((r = sshbuf_get_string_direct(m, &input, &ilen)) != 0 ||
(r = sshbuf_get_string_direct(m, &output, &olen)) != 0 ||
(r = sshbuf_put(state->input, input, ilen)) != 0 ||
(r = sshbuf_put(state->output, output, olen)) != 0)
return r;
if (sshbuf_len(m))
return SSH_ERR_INVALID_FORMAT;
debug3("%s: done", __func__);
return 0;
}
/* NEW API */
/* put data to the outgoing packet */
int
sshpkt_put(struct ssh *ssh, const void *v, size_t len)
{
return sshbuf_put(ssh->state->outgoing_packet, v, len);
}
int
sshpkt_putb(struct ssh *ssh, const struct sshbuf *b)
{
return sshbuf_putb(ssh->state->outgoing_packet, b);
}
int
sshpkt_put_u8(struct ssh *ssh, u_char val)
{
return sshbuf_put_u8(ssh->state->outgoing_packet, val);
}
int
sshpkt_put_u32(struct ssh *ssh, u_int32_t val)
{
return sshbuf_put_u32(ssh->state->outgoing_packet, val);
}
int
sshpkt_put_u64(struct ssh *ssh, u_int64_t val)
{
return sshbuf_put_u64(ssh->state->outgoing_packet, val);
}
int
sshpkt_put_string(struct ssh *ssh, const void *v, size_t len)
{
return sshbuf_put_string(ssh->state->outgoing_packet, v, len);
}
int
sshpkt_put_cstring(struct ssh *ssh, const void *v)
{
return sshbuf_put_cstring(ssh->state->outgoing_packet, v);
}
int
sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v)
{
return sshbuf_put_stringb(ssh->state->outgoing_packet, v);
}
+int
+sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp)
+{
+ return sshbuf_froms(ssh->state->incoming_packet, valp);
+}
+
#ifdef WITH_OPENSSL
#ifdef OPENSSL_HAS_ECC
int
sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g)
{
return sshbuf_put_ec(ssh->state->outgoing_packet, v, g);
}
#endif /* OPENSSL_HAS_ECC */
int
sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v)
{
return sshbuf_put_bignum2(ssh->state->outgoing_packet, v);
}
#endif /* WITH_OPENSSL */
/* fetch data from the incoming packet */
int
sshpkt_get(struct ssh *ssh, void *valp, size_t len)
{
return sshbuf_get(ssh->state->incoming_packet, valp, len);
}
int
sshpkt_get_u8(struct ssh *ssh, u_char *valp)
{
return sshbuf_get_u8(ssh->state->incoming_packet, valp);
}
int
sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp)
{
return sshbuf_get_u32(ssh->state->incoming_packet, valp);
}
int
sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp)
{
return sshbuf_get_u64(ssh->state->incoming_packet, valp);
}
int
sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp)
{
return sshbuf_get_string(ssh->state->incoming_packet, valp, lenp);
}
int
sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
{
return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp);
}
int
sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
{
return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp);
}
int
sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp)
{
return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp);
}
#ifdef WITH_OPENSSL
#ifdef OPENSSL_HAS_ECC
int
sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g)
{
return sshbuf_get_ec(ssh->state->incoming_packet, v, g);
}
#endif /* OPENSSL_HAS_ECC */
-
int
-sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v)
+sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp)
{
- return sshbuf_get_bignum2(ssh->state->incoming_packet, v);
+ return sshbuf_get_bignum2(ssh->state->incoming_packet, valp);
}
#endif /* WITH_OPENSSL */
int
sshpkt_get_end(struct ssh *ssh)
{
if (sshbuf_len(ssh->state->incoming_packet) > 0)
return SSH_ERR_UNEXPECTED_TRAILING_DATA;
return 0;
}
const u_char *
sshpkt_ptr(struct ssh *ssh, size_t *lenp)
{
if (lenp != NULL)
*lenp = sshbuf_len(ssh->state->incoming_packet);
return sshbuf_ptr(ssh->state->incoming_packet);
}
/* start a new packet */
int
sshpkt_start(struct ssh *ssh, u_char type)
{
u_char buf[6]; /* u32 packet length, u8 pad len, u8 type */
DBG(debug("packet_start[%d]", type));
memset(buf, 0, sizeof(buf));
buf[sizeof(buf) - 1] = type;
sshbuf_reset(ssh->state->outgoing_packet);
return sshbuf_put(ssh->state->outgoing_packet, buf, sizeof(buf));
}
static int
ssh_packet_send_mux(struct ssh *ssh)
{
struct session_state *state = ssh->state;
u_char type, *cp;
size_t len;
int r;
if (ssh->kex)
return SSH_ERR_INTERNAL_ERROR;
len = sshbuf_len(state->outgoing_packet);
if (len < 6)
return SSH_ERR_INTERNAL_ERROR;
cp = sshbuf_mutable_ptr(state->outgoing_packet);
type = cp[5];
if (ssh_packet_log_type(type))
debug3("%s: type %u", __func__, type);
/* drop everything, but the connection protocol */
if (type >= SSH2_MSG_CONNECTION_MIN &&
type <= SSH2_MSG_CONNECTION_MAX) {
POKE_U32(cp, len - 4);
if ((r = sshbuf_putb(state->output,
state->outgoing_packet)) != 0)
return r;
/* sshbuf_dump(state->output, stderr); */
}
sshbuf_reset(state->outgoing_packet);
return 0;
}
/*
* 9.2. Ignored Data Message
*
* byte SSH_MSG_IGNORE
* string data
*
* All implementations MUST understand (and ignore) this message at any
* time (after receiving the protocol version). No implementation is
* required to send them. This message can be used as an additional
* protection measure against advanced traffic analysis techniques.
*/
int
sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes)
{
u_int32_t rnd = 0;
int r;
u_int i;
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_u32(ssh, nbytes)) != 0)
return r;
for (i = 0; i < nbytes; i++) {
if (i % 4 == 0)
rnd = arc4random();
if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
return r;
rnd >>= 8;
}
return 0;
}
/* send it */
int
sshpkt_send(struct ssh *ssh)
{
if (ssh->state && ssh->state->mux)
return ssh_packet_send_mux(ssh);
return ssh_packet_send2(ssh);
}
int
sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
{
char buf[1024];
va_list args;
int r;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
return 0;
}
/* roundup current message to pad bytes */
int
sshpkt_add_padding(struct ssh *ssh, u_char pad)
{
ssh->state->extra_pad = pad;
return 0;
}
diff --git a/packet.h b/packet.h
index 170203cabeb2..0dfa36da1350 100644
--- a/packet.h
+++ b/packet.h
@@ -1,222 +1,220 @@
-/* $OpenBSD: packet.h,v 1.86 2018/07/09 21:20:26 markus Exp $ */
+/* $OpenBSD: packet.h,v 1.90 2019/01/21 10:35:09 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Interface for the packet protocol functions.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef PACKET_H
#define PACKET_H
#include <termios.h>
#ifdef WITH_OPENSSL
# include <openssl/bn.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# else /* OPENSSL_HAS_ECC */
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
#else /* WITH_OPENSSL */
# define BIGNUM void
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
#endif /* WITH_OPENSSL */
#include <signal.h>
#include "openbsd-compat/sys-queue.h"
struct kex;
struct sshkey;
struct sshbuf;
struct session_state; /* private session data */
#include "dispatch.h" /* typedef, DISPATCH_MAX */
struct key_entry {
TAILQ_ENTRY(key_entry) next;
struct sshkey *key;
};
struct ssh {
/* Session state */
struct session_state *state;
/* Key exchange */
struct kex *kex;
/* cached local and remote ip addresses and ports */
char *remote_ipaddr;
int remote_port;
char *local_ipaddr;
int local_port;
char *rdomain_in;
/* Optional preamble for log messages (e.g. username) */
char *log_preamble;
/* Dispatcher table */
dispatch_fn *dispatch[DISPATCH_MAX];
/* number of packets to ignore in the dispatcher */
int dispatch_skip_packets;
/* datafellows */
int compat;
/* Lists for private and public keys */
TAILQ_HEAD(, key_entry) private_keys;
TAILQ_HEAD(, key_entry) public_keys;
/* Client/Server authentication context */
void *authctxt;
/* Channels context */
struct ssh_channels *chanctxt;
/* APP data */
void *app_data;
};
typedef int (ssh_packet_hook_fn)(struct ssh *, struct sshbuf *,
u_char *, void *);
struct ssh *ssh_alloc_session_state(void);
struct ssh *ssh_packet_set_connection(struct ssh *, int, int);
void ssh_packet_set_timeout(struct ssh *, int, int);
int ssh_packet_stop_discard(struct ssh *);
int ssh_packet_connection_af(struct ssh *);
void ssh_packet_set_nonblocking(struct ssh *);
int ssh_packet_get_connection_in(struct ssh *);
int ssh_packet_get_connection_out(struct ssh *);
void ssh_packet_close(struct ssh *);
void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *);
void ssh_packet_clear_keys(struct ssh *);
void ssh_clear_newkeys(struct ssh *, int);
int ssh_packet_is_rekeying(struct ssh *);
void ssh_packet_set_protocol_flags(struct ssh *, u_int);
u_int ssh_packet_get_protocol_flags(struct ssh *);
void ssh_packet_set_tos(struct ssh *, int);
void ssh_packet_set_interactive(struct ssh *, int, int, int);
int ssh_packet_is_interactive(struct ssh *);
void ssh_packet_set_server(struct ssh *);
void ssh_packet_set_authenticated(struct ssh *);
void ssh_packet_set_mux(struct ssh *);
int ssh_packet_get_mux(struct ssh *);
int ssh_packet_set_log_preamble(struct ssh *, const char *, ...)
__attribute__((format(printf, 2, 3)));
int ssh_packet_log_type(u_char);
int ssh_packet_send2_wrapped(struct ssh *);
int ssh_packet_send2(struct ssh *);
int ssh_packet_read(struct ssh *);
int ssh_packet_read_expect(struct ssh *, u_int type);
int ssh_packet_read_poll(struct ssh *);
int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p);
int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len);
int ssh_packet_read_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p);
int ssh_packet_read_poll_seqnr(struct ssh *, u_char *, u_int32_t *seqnr_p);
const void *ssh_packet_get_string_ptr(struct ssh *, u_int *length_ptr);
void ssh_packet_disconnect(struct ssh *, const char *fmt, ...)
__attribute__((format(printf, 2, 3)))
__attribute__((noreturn));
void ssh_packet_send_debug(struct ssh *, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
int ssh_set_newkeys(struct ssh *, int mode);
void ssh_packet_get_bytes(struct ssh *, u_int64_t *, u_int64_t *);
int ssh_packet_write_poll(struct ssh *);
int ssh_packet_write_wait(struct ssh *);
int ssh_packet_have_data_to_write(struct ssh *);
int ssh_packet_not_very_much_data_to_write(struct ssh *);
int ssh_packet_connection_is_on_socket(struct ssh *);
int ssh_packet_remaining(struct ssh *);
void ssh_tty_make_modes(struct ssh *, int, struct termios *);
void ssh_tty_parse_modes(struct ssh *, int);
void ssh_packet_set_alive_timeouts(struct ssh *, int);
int ssh_packet_inc_alive_timeouts(struct ssh *);
int ssh_packet_set_maxsize(struct ssh *, u_int);
u_int ssh_packet_get_maxsize(struct ssh *);
int ssh_packet_get_state(struct ssh *, struct sshbuf *);
int ssh_packet_set_state(struct ssh *, struct sshbuf *);
const char *ssh_remote_ipaddr(struct ssh *);
int ssh_remote_port(struct ssh *);
const char *ssh_local_ipaddr(struct ssh *);
int ssh_local_port(struct ssh *);
const char *ssh_packet_rdomain_in(struct ssh *);
void ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, u_int32_t);
time_t ssh_packet_get_rekey_timeout(struct ssh *);
void *ssh_packet_get_input(struct ssh *);
void *ssh_packet_get_output(struct ssh *);
/* new API */
int sshpkt_start(struct ssh *ssh, u_char type);
int sshpkt_send(struct ssh *ssh);
int sshpkt_disconnect(struct ssh *, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
int sshpkt_add_padding(struct ssh *, u_char);
-void sshpkt_fatal(struct ssh *ssh, const char *tag, int r);
+void sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...)
+ __attribute__((format(printf, 3, 4)));
int sshpkt_msg_ignore(struct ssh *, u_int);
int sshpkt_put(struct ssh *ssh, const void *v, size_t len);
int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b);
int sshpkt_put_u8(struct ssh *ssh, u_char val);
int sshpkt_put_u32(struct ssh *ssh, u_int32_t val);
int sshpkt_put_u64(struct ssh *ssh, u_int64_t val);
int sshpkt_put_string(struct ssh *ssh, const void *v, size_t len);
int sshpkt_put_cstring(struct ssh *ssh, const void *v);
int sshpkt_put_stringb(struct ssh *ssh, const struct sshbuf *v);
int sshpkt_put_ec(struct ssh *ssh, const EC_POINT *v, const EC_GROUP *g);
int sshpkt_put_bignum2(struct ssh *ssh, const BIGNUM *v);
int sshpkt_get(struct ssh *ssh, void *valp, size_t len);
int sshpkt_get_u8(struct ssh *ssh, u_char *valp);
int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp);
int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp);
int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp);
int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp);
+int sshpkt_getb_froms(struct ssh *ssh, struct sshbuf **valp);
int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g);
-int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v);
+int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM **valp);
int sshpkt_get_end(struct ssh *ssh);
void sshpkt_fmt_connection_id(struct ssh *ssh, char *s, size_t l);
const u_char *sshpkt_ptr(struct ssh *, size_t *lenp);
-/* OLD API */
-extern struct ssh *active_state;
-#include "opacket.h"
-
#if !defined(WITH_OPENSSL)
# undef BIGNUM
# undef EC_KEY
# undef EC_GROUP
# undef EC_POINT
#elif !defined(OPENSSL_HAS_ECC)
# undef EC_KEY
# undef EC_GROUP
# undef EC_POINT
#endif
#endif /* PACKET_H */
diff --git a/progressmeter.c b/progressmeter.c
index fe9bf52e4c90..e385c1254ccc 100644
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -1,306 +1,298 @@
-/* $OpenBSD: progressmeter.c,v 1.45 2016/06/30 05:17:05 dtucker Exp $ */
+/* $OpenBSD: progressmeter.c,v 1.47 2019/01/24 16:52:17 dtucker Exp $ */
/*
* Copyright (c) 2003 Nils Nordman. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <errno.h>
#include <signal.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "progressmeter.h"
#include "atomicio.h"
#include "misc.h"
+#include "utf8.h"
#define DEFAULT_WINSIZE 80
#define MAX_WINSIZE 512
#define PADDING 1 /* padding between the progress indicators */
#define UPDATE_INTERVAL 1 /* update the progress meter every second */
#define STALL_TIME 5 /* we're stalled after this many seconds */
/* determines whether we can output to the terminal */
static int can_output(void);
/* formats and inserts the specified size into the given buffer */
static void format_size(char *, int, off_t);
static void format_rate(char *, int, off_t);
/* window resizing */
static void sig_winch(int);
static void setscreensize(void);
-/* updates the progressmeter to reflect the current state of the transfer */
-void refresh_progress_meter(void);
-
/* signal handler for updating the progress meter */
-static void update_progress_meter(int);
+static void sig_alarm(int);
static double start; /* start progress */
static double last_update; /* last progress update */
static const char *file; /* name of the file being transferred */
static off_t start_pos; /* initial position of transfer */
static off_t end_pos; /* ending position of transfer */
static off_t cur_pos; /* transfer position as of last refresh */
static volatile off_t *counter; /* progress counter */
static long stalled; /* how long we have been stalled */
static int bytes_per_second; /* current speed in bytes per second */
static int win_size; /* terminal window size */
static volatile sig_atomic_t win_resized; /* for window resizing */
+static volatile sig_atomic_t alarm_fired;
/* units for format_size */
static const char unit[] = " KMGT";
static int
can_output(void)
{
return (getpgrp() == tcgetpgrp(STDOUT_FILENO));
}
static void
format_rate(char *buf, int size, off_t bytes)
{
int i;
bytes *= 100;
for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
bytes = (bytes + 512) / 1024;
if (i == 0) {
i++;
bytes = (bytes + 512) / 1024;
}
snprintf(buf, size, "%3lld.%1lld%c%s",
(long long) (bytes + 5) / 100,
(long long) (bytes + 5) / 10 % 10,
unit[i],
i ? "B" : " ");
}
static void
format_size(char *buf, int size, off_t bytes)
{
int i;
for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
bytes = (bytes + 512) / 1024;
snprintf(buf, size, "%4lld%c%s",
(long long) bytes,
unit[i],
i ? "B" : " ");
}
void
-refresh_progress_meter(void)
+refresh_progress_meter(int force_update)
{
char buf[MAX_WINSIZE + 1];
off_t transferred;
double elapsed, now;
int percent;
off_t bytes_left;
int cur_speed;
int hours, minutes, seconds;
- int i, len;
int file_len;
+ if ((!force_update && !alarm_fired && !win_resized) || !can_output())
+ return;
+ alarm_fired = 0;
+
+ if (win_resized) {
+ setscreensize();
+ win_resized = 0;
+ }
+
transferred = *counter - (cur_pos ? cur_pos : start_pos);
cur_pos = *counter;
now = monotime_double();
bytes_left = end_pos - cur_pos;
if (bytes_left > 0)
elapsed = now - last_update;
else {
elapsed = now - start;
/* Calculate true total speed when done */
transferred = end_pos - start_pos;
bytes_per_second = 0;
}
/* calculate speed */
if (elapsed != 0)
cur_speed = (transferred / elapsed);
else
cur_speed = transferred;
#define AGE_FACTOR 0.9
if (bytes_per_second != 0) {
bytes_per_second = (bytes_per_second * AGE_FACTOR) +
(cur_speed * (1.0 - AGE_FACTOR));
} else
bytes_per_second = cur_speed;
/* filename */
buf[0] = '\0';
- file_len = win_size - 35;
+ file_len = win_size - 36;
if (file_len > 0) {
- len = snprintf(buf, file_len + 1, "\r%s", file);
- if (len < 0)
- len = 0;
- if (len >= file_len + 1)
- len = file_len;
- for (i = len; i < file_len; i++)
- buf[i] = ' ';
- buf[file_len] = '\0';
+ buf[0] = '\r';
+ snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s",
+ file_len * -1, file);
}
/* percent of transfer done */
if (end_pos == 0 || cur_pos == end_pos)
percent = 100;
else
percent = ((float)cur_pos / end_pos) * 100;
snprintf(buf + strlen(buf), win_size - strlen(buf),
" %3d%% ", percent);
/* amount transferred */
format_size(buf + strlen(buf), win_size - strlen(buf),
cur_pos);
strlcat(buf, " ", win_size);
/* bandwidth usage */
format_rate(buf + strlen(buf), win_size - strlen(buf),
(off_t)bytes_per_second);
strlcat(buf, "/s ", win_size);
/* ETA */
if (!transferred)
stalled += elapsed;
else
stalled = 0;
if (stalled >= STALL_TIME)
strlcat(buf, "- stalled -", win_size);
else if (bytes_per_second == 0 && bytes_left)
strlcat(buf, " --:-- ETA", win_size);
else {
if (bytes_left > 0)
seconds = bytes_left / bytes_per_second;
else
seconds = elapsed;
hours = seconds / 3600;
seconds -= hours * 3600;
minutes = seconds / 60;
seconds -= minutes * 60;
if (hours != 0)
snprintf(buf + strlen(buf), win_size - strlen(buf),
"%d:%02d:%02d", hours, minutes, seconds);
else
snprintf(buf + strlen(buf), win_size - strlen(buf),
" %02d:%02d", minutes, seconds);
if (bytes_left > 0)
strlcat(buf, " ETA", win_size);
else
strlcat(buf, " ", win_size);
}
atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
last_update = now;
}
/*ARGSUSED*/
static void
-update_progress_meter(int ignore)
+sig_alarm(int ignore)
{
- int save_errno;
-
- save_errno = errno;
-
- if (win_resized) {
- setscreensize();
- win_resized = 0;
- }
- if (can_output())
- refresh_progress_meter();
-
- signal(SIGALRM, update_progress_meter);
+ signal(SIGALRM, sig_alarm);
+ alarm_fired = 1;
alarm(UPDATE_INTERVAL);
- errno = save_errno;
}
void
start_progress_meter(const char *f, off_t filesize, off_t *ctr)
{
start = last_update = monotime_double();
file = f;
start_pos = *ctr;
end_pos = filesize;
cur_pos = 0;
counter = ctr;
stalled = 0;
bytes_per_second = 0;
setscreensize();
- if (can_output())
- refresh_progress_meter();
+ refresh_progress_meter(1);
- signal(SIGALRM, update_progress_meter);
+ signal(SIGALRM, sig_alarm);
signal(SIGWINCH, sig_winch);
alarm(UPDATE_INTERVAL);
}
void
stop_progress_meter(void)
{
alarm(0);
if (!can_output())
return;
/* Ensure we complete the progress */
if (cur_pos != end_pos)
- refresh_progress_meter();
+ refresh_progress_meter(1);
atomicio(vwrite, STDOUT_FILENO, "\n", 1);
}
/*ARGSUSED*/
static void
sig_winch(int sig)
{
+ signal(SIGWINCH, sig_winch);
win_resized = 1;
}
static void
setscreensize(void)
{
struct winsize winsize;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
winsize.ws_col != 0) {
if (winsize.ws_col > MAX_WINSIZE)
win_size = MAX_WINSIZE;
else
win_size = winsize.ws_col;
} else
win_size = DEFAULT_WINSIZE;
win_size += 1; /* trailing \0 */
}
diff --git a/progressmeter.h b/progressmeter.h
index bf179dca6518..1703ea75babc 100644
--- a/progressmeter.h
+++ b/progressmeter.h
@@ -1,27 +1,28 @@
-/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */
+/* $OpenBSD: progressmeter.h,v 1.5 2019/01/24 16:52:17 dtucker Exp $ */
/*
* Copyright (c) 2002 Nils Nordman. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
void start_progress_meter(const char *, off_t, off_t *);
+void refresh_progress_meter(int);
void stop_progress_meter(void);
diff --git a/readconf.c b/readconf.c
index 433811521bb1..ec497e79fcd0 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,2757 +1,2770 @@
-/* $OpenBSD: readconf.c,v 1.300 2018/10/05 14:26:09 naddy Exp $ */
+/* $OpenBSD: readconf.c,v 1.304 2019/03/01 02:08:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for reading the configuration files.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#ifdef USE_SYSTEM_GLOB
# include <glob.h>
#else
# include "openbsd-compat/glob.h"
#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
# include <vis.h>
#endif
#include "xmalloc.h"
#include "ssh.h"
#include "ssherr.h"
#include "compat.h"
#include "cipher.h"
#include "pathnames.h"
#include "log.h"
#include "sshkey.h"
#include "misc.h"
#include "readconf.h"
#include "match.h"
#include "kex.h"
#include "mac.h"
#include "uidswap.h"
#include "myproposal.h"
#include "digest.h"
/* Format of the configuration file:
# Configuration data is parsed as follows:
# 1. command line options
# 2. user-specific file
# 3. system-wide file
# Any configuration value is only changed the first time it is set.
# Thus, host-specific definitions should be at the beginning of the
# configuration file, and defaults at the end.
# Host-specific declarations. These may override anything above. A single
# host may match multiple declarations; these are processed in the order
# that they are given in.
Host *.ngs.fi ngs.fi
User foo
Host fake.com
HostName another.host.name.real.org
User blaah
Port 34289
ForwardX11 no
ForwardAgent no
Host books.com
RemoteForward 9999 shadows.cs.hut.fi:9999
Ciphers 3des-cbc
Host fascist.blob.com
Port 23123
User tylonen
PasswordAuthentication no
Host puukko.hut.fi
User t35124p
ProxyCommand ssh-proxy %h %p
Host *.fr
PublicKeyAuthentication no
Host *.su
Ciphers aes128-ctr
PasswordAuthentication no
Host vpn.fake.com
Tunnel yes
TunnelDevice 3
# Defaults for various options
Host *
ForwardAgent no
ForwardX11 no
PasswordAuthentication yes
RSAAuthentication yes
RhostsRSAAuthentication yes
StrictHostKeyChecking yes
TcpKeepAlive no
IdentityFile ~/.ssh/identity
Port 22
EscapeChar ~
*/
static int read_config_file_depth(const char *filename, struct passwd *pw,
const char *host, const char *original_host, Options *options,
- int flags, int *activep, int depth);
+ int flags, int *activep, int *want_final_pass, int depth);
static int process_config_line_depth(Options *options, struct passwd *pw,
const char *host, const char *original_host, char *line,
- const char *filename, int linenum, int *activep, int flags, int depth);
+ const char *filename, int linenum, int *activep, int flags,
+ int *want_final_pass, int depth);
/* Keyword tokens. */
typedef enum {
oBadOption,
oHost, oMatch, oInclude,
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
oGatewayPorts, oExitOnForwardFailure,
oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
oCertificateFile, oAddKeysToAgent, oIdentityAgent,
oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs,
oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
oClearAllForwardings, oNoHostAuthenticationForLocalhost,
oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
oAddressFamily, oGssAuthentication, oGssDelegateCreds,
oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
oTunnel, oTunnelDevice,
oLocalCommand, oPermitLocalCommand, oRemoteCommand,
oVisualHostKey,
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump,
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
/* Textual representations of the tokens. */
static struct {
const char *name;
OpCodes opcode;
} keywords[] = {
/* Deprecated options */
{ "protocol", oIgnore }, /* NB. silently ignored */
{ "cipher", oDeprecated },
{ "fallbacktorsh", oDeprecated },
{ "globalknownhostsfile2", oDeprecated },
{ "rhostsauthentication", oDeprecated },
{ "userknownhostsfile2", oDeprecated },
{ "useroaming", oDeprecated },
{ "usersh", oDeprecated },
{ "useprivilegedport", oDeprecated },
/* Unsupported options */
{ "afstokenpassing", oUnsupported },
{ "kerberosauthentication", oUnsupported },
{ "kerberostgtpassing", oUnsupported },
/* Sometimes-unsupported options */
#if defined(GSSAPI)
{ "gssapiauthentication", oGssAuthentication },
{ "gssapidelegatecredentials", oGssDelegateCreds },
# else
{ "gssapiauthentication", oUnsupported },
{ "gssapidelegatecredentials", oUnsupported },
#endif
#ifdef ENABLE_PKCS11
- { "smartcarddevice", oPKCS11Provider },
{ "pkcs11provider", oPKCS11Provider },
+ { "smartcarddevice", oPKCS11Provider },
# else
{ "smartcarddevice", oUnsupported },
{ "pkcs11provider", oUnsupported },
#endif
{ "rsaauthentication", oUnsupported },
{ "rhostsrsaauthentication", oUnsupported },
{ "compressionlevel", oUnsupported },
{ "forwardagent", oForwardAgent },
{ "forwardx11", oForwardX11 },
{ "forwardx11trusted", oForwardX11Trusted },
{ "forwardx11timeout", oForwardX11Timeout },
{ "exitonforwardfailure", oExitOnForwardFailure },
{ "xauthlocation", oXAuthLocation },
{ "gatewayports", oGatewayPorts },
{ "passwordauthentication", oPasswordAuthentication },
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
{ "kbdinteractivedevices", oKbdInteractiveDevices },
{ "pubkeyauthentication", oPubkeyAuthentication },
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
{ "hostbasedauthentication", oHostbasedAuthentication },
{ "challengeresponseauthentication", oChallengeResponseAuthentication },
{ "skeyauthentication", oUnsupported },
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* obsolete */
{ "identitiesonly", oIdentitiesOnly },
{ "certificatefile", oCertificateFile },
{ "addkeystoagent", oAddKeysToAgent },
{ "identityagent", oIdentityAgent },
{ "hostname", oHostName },
{ "hostkeyalias", oHostKeyAlias },
{ "proxycommand", oProxyCommand },
{ "port", oPort },
{ "ciphers", oCiphers },
{ "macs", oMacs },
{ "remoteforward", oRemoteForward },
{ "localforward", oLocalForward },
{ "user", oUser },
{ "host", oHost },
{ "match", oMatch },
{ "escapechar", oEscapeChar },
{ "globalknownhostsfile", oGlobalKnownHostsFile },
{ "userknownhostsfile", oUserKnownHostsFile },
{ "connectionattempts", oConnectionAttempts },
{ "batchmode", oBatchMode },
{ "checkhostip", oCheckHostIP },
{ "stricthostkeychecking", oStrictHostKeyChecking },
{ "compression", oCompression },
{ "tcpkeepalive", oTCPKeepAlive },
{ "keepalive", oTCPKeepAlive }, /* obsolete */
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "syslogfacility", oLogFacility },
{ "loglevel", oLogLevel },
{ "dynamicforward", oDynamicForward },
{ "preferredauthentications", oPreferredAuthentications },
{ "hostkeyalgorithms", oHostKeyAlgorithms },
{ "casignaturealgorithms", oCASignatureAlgorithms },
{ "bindaddress", oBindAddress },
{ "bindinterface", oBindInterface },
{ "clearallforwardings", oClearAllForwardings },
{ "enablesshkeysign", oEnableSSHKeysign },
{ "verifyhostkeydns", oVerifyHostKeyDNS },
{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
{ "rekeylimit", oRekeyLimit },
{ "connecttimeout", oConnectTimeout },
{ "addressfamily", oAddressFamily },
{ "serveraliveinterval", oServerAliveInterval },
{ "serveralivecountmax", oServerAliveCountMax },
{ "sendenv", oSendEnv },
{ "setenv", oSetEnv },
{ "controlpath", oControlPath },
{ "controlmaster", oControlMaster },
{ "controlpersist", oControlPersist },
{ "hashknownhosts", oHashKnownHosts },
{ "include", oInclude },
{ "tunnel", oTunnel },
{ "tunneldevice", oTunnelDevice },
{ "localcommand", oLocalCommand },
{ "permitlocalcommand", oPermitLocalCommand },
{ "remotecommand", oRemoteCommand },
{ "visualhostkey", oVisualHostKey },
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ "requesttty", oRequestTTY },
{ "proxyusefdpass", oProxyUseFdpass },
{ "canonicaldomains", oCanonicalDomains },
{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
{ "canonicalizehostname", oCanonicalizeHostname },
{ "canonicalizemaxdots", oCanonicalizeMaxDots },
{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
{ "streamlocalbindmask", oStreamLocalBindMask },
{ "streamlocalbindunlink", oStreamLocalBindUnlink },
{ "revokedhostkeys", oRevokedHostKeys },
{ "fingerprinthash", oFingerprintHash },
{ "updatehostkeys", oUpdateHostkeys },
{ "hostbasedkeytypes", oHostbasedKeyTypes },
{ "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
{ "ignoreunknown", oIgnoreUnknown },
{ "proxyjump", oProxyJump },
{ NULL, oBadOption }
};
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
*/
void
add_local_forward(Options *options, const struct Forward *newfwd)
{
struct Forward *fwd;
int i;
/* Don't add duplicates */
for (i = 0; i < options->num_local_forwards; i++) {
if (forward_equals(newfwd, options->local_forwards + i))
return;
}
options->local_forwards = xreallocarray(options->local_forwards,
options->num_local_forwards + 1,
sizeof(*options->local_forwards));
fwd = &options->local_forwards[options->num_local_forwards++];
fwd->listen_host = newfwd->listen_host;
fwd->listen_port = newfwd->listen_port;
fwd->listen_path = newfwd->listen_path;
fwd->connect_host = newfwd->connect_host;
fwd->connect_port = newfwd->connect_port;
fwd->connect_path = newfwd->connect_path;
}
/*
* Adds a remote TCP/IP port forward to options. Never returns if there is
* an error.
*/
void
add_remote_forward(Options *options, const struct Forward *newfwd)
{
struct Forward *fwd;
int i;
/* Don't add duplicates */
for (i = 0; i < options->num_remote_forwards; i++) {
if (forward_equals(newfwd, options->remote_forwards + i))
return;
}
options->remote_forwards = xreallocarray(options->remote_forwards,
options->num_remote_forwards + 1,
sizeof(*options->remote_forwards));
fwd = &options->remote_forwards[options->num_remote_forwards++];
fwd->listen_host = newfwd->listen_host;
fwd->listen_port = newfwd->listen_port;
fwd->listen_path = newfwd->listen_path;
fwd->connect_host = newfwd->connect_host;
fwd->connect_port = newfwd->connect_port;
fwd->connect_path = newfwd->connect_path;
fwd->handle = newfwd->handle;
fwd->allocated_port = 0;
}
static void
clear_forwardings(Options *options)
{
int i;
for (i = 0; i < options->num_local_forwards; i++) {
free(options->local_forwards[i].listen_host);
free(options->local_forwards[i].listen_path);
free(options->local_forwards[i].connect_host);
free(options->local_forwards[i].connect_path);
}
if (options->num_local_forwards > 0) {
free(options->local_forwards);
options->local_forwards = NULL;
}
options->num_local_forwards = 0;
for (i = 0; i < options->num_remote_forwards; i++) {
free(options->remote_forwards[i].listen_host);
free(options->remote_forwards[i].listen_path);
free(options->remote_forwards[i].connect_host);
free(options->remote_forwards[i].connect_path);
}
if (options->num_remote_forwards > 0) {
free(options->remote_forwards);
options->remote_forwards = NULL;
}
options->num_remote_forwards = 0;
options->tun_open = SSH_TUNMODE_NO;
}
void
add_certificate_file(Options *options, const char *path, int userprovided)
{
int i;
if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
fatal("Too many certificate files specified (max %d)",
SSH_MAX_CERTIFICATE_FILES);
/* Avoid registering duplicates */
for (i = 0; i < options->num_certificate_files; i++) {
if (options->certificate_file_userprovided[i] == userprovided &&
strcmp(options->certificate_files[i], path) == 0) {
debug2("%s: ignoring duplicate key %s", __func__, path);
return;
}
}
options->certificate_file_userprovided[options->num_certificate_files] =
userprovided;
options->certificate_files[options->num_certificate_files++] =
xstrdup(path);
}
void
add_identity_file(Options *options, const char *dir, const char *filename,
int userprovided)
{
char *path;
int i;
if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
fatal("Too many identity files specified (max %d)",
SSH_MAX_IDENTITY_FILES);
if (dir == NULL) /* no dir, filename is absolute */
path = xstrdup(filename);
else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
fatal("Identity file path %s too long", path);
/* Avoid registering duplicates */
for (i = 0; i < options->num_identity_files; i++) {
if (options->identity_file_userprovided[i] == userprovided &&
strcmp(options->identity_files[i], path) == 0) {
debug2("%s: ignoring duplicate key %s", __func__, path);
free(path);
return;
}
}
options->identity_file_userprovided[options->num_identity_files] =
userprovided;
options->identity_files[options->num_identity_files++] = path;
}
int
default_ssh_port(void)
{
static int port;
struct servent *sp;
if (port == 0) {
sp = getservbyname(SSH_SERVICE_NAME, "tcp");
port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
}
return port;
}
/*
* Execute a command in a shell.
* Return its exit status or -1 on abnormal exit.
*/
static int
execute_in_shell(const char *cmd)
{
char *shell;
pid_t pid;
int devnull, status;
if ((shell = getenv("SHELL")) == NULL)
shell = _PATH_BSHELL;
/* Need this to redirect subprocess stdin/out */
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
fatal("open(/dev/null): %s", strerror(errno));
debug("Executing command: '%.500s'", cmd);
/* Fork and execute the command. */
if ((pid = fork()) == 0) {
char *argv[4];
/* Redirect child stdin and stdout. Leave stderr */
if (dup2(devnull, STDIN_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
if (dup2(devnull, STDOUT_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
if (devnull > STDERR_FILENO)
close(devnull);
closefrom(STDERR_FILENO + 1);
argv[0] = shell;
argv[1] = "-c";
argv[2] = xstrdup(cmd);
argv[3] = NULL;
execv(argv[0], argv);
error("Unable to execute '%.100s': %s", cmd, strerror(errno));
/* Die with signal to make this error apparent to parent. */
signal(SIGTERM, SIG_DFL);
kill(getpid(), SIGTERM);
_exit(1);
}
/* Parent. */
if (pid < 0)
fatal("%s: fork: %.100s", __func__, strerror(errno));
close(devnull);
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR && errno != EAGAIN)
fatal("%s: waitpid: %s", __func__, strerror(errno));
}
if (!WIFEXITED(status)) {
error("command '%.100s' exited abnormally", cmd);
return -1;
}
debug3("command returned status %d", WEXITSTATUS(status));
return WEXITSTATUS(status);
}
/*
* Parse and execute a Match directive.
*/
static int
match_cfg_line(Options *options, char **condition, struct passwd *pw,
- const char *host_arg, const char *original_host, int post_canon,
- const char *filename, int linenum)
+ const char *host_arg, const char *original_host, int final_pass,
+ int *want_final_pass, const char *filename, int linenum)
{
char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
const char *ruser;
int r, port, this_result, result = 1, attributes = 0, negate;
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
char uidstr[32];
/*
* Configuration is likely to be incomplete at this point so we
* must be prepared to use default values.
*/
port = options->port <= 0 ? default_ssh_port() : options->port;
ruser = options->user == NULL ? pw->pw_name : options->user;
- if (post_canon) {
+ if (final_pass) {
host = xstrdup(options->hostname);
} else if (options->hostname != NULL) {
/* NB. Please keep in sync with ssh.c:main() */
host = percent_expand(options->hostname,
"h", host_arg, (char *)NULL);
} else {
host = xstrdup(host_arg);
}
debug2("checking match for '%s' host %s originally %s",
cp, host, original_host);
while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
criteria = NULL;
this_result = 1;
if ((negate = attrib[0] == '!'))
attrib++;
/* criteria "all" and "canonical" have no argument */
if (strcasecmp(attrib, "all") == 0) {
if (attributes > 1 ||
((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
error("%.200s line %d: '%s' cannot be combined "
"with other Match attributes",
filename, linenum, oattrib);
result = -1;
goto out;
}
if (result)
result = negate ? 0 : 1;
goto out;
}
attributes++;
- if (strcasecmp(attrib, "canonical") == 0) {
- r = !!post_canon; /* force bitmask member to boolean */
+ if (strcasecmp(attrib, "canonical") == 0 ||
+ strcasecmp(attrib, "final") == 0) {
+ /*
+ * If the config requests "Match final" then remember
+ * this so we can perform a second pass later.
+ */
+ if (strcasecmp(attrib, "final") == 0 &&
+ want_final_pass != NULL)
+ *want_final_pass = 1;
+ r = !!final_pass; /* force bitmask member to boolean */
if (r == (negate ? 1 : 0))
this_result = result = 0;
debug3("%.200s line %d: %smatched '%s'",
filename, linenum,
this_result ? "" : "not ", oattrib);
continue;
}
/* All other criteria require an argument */
if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
error("Missing Match criteria for %s", attrib);
result = -1;
goto out;
}
if (strcasecmp(attrib, "host") == 0) {
criteria = xstrdup(host);
r = match_hostname(host, arg) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "originalhost") == 0) {
criteria = xstrdup(original_host);
r = match_hostname(original_host, arg) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "user") == 0) {
criteria = xstrdup(ruser);
r = match_pattern_list(ruser, arg, 0) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "localuser") == 0) {
criteria = xstrdup(pw->pw_name);
r = match_pattern_list(pw->pw_name, arg, 0) == 1;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "exec") == 0) {
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
strlcpy(shorthost, thishost, sizeof(shorthost));
shorthost[strcspn(thishost, ".")] = '\0';
snprintf(portstr, sizeof(portstr), "%d", port);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
cmd = percent_expand(arg,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
"l", thishost,
"n", original_host,
"p", portstr,
"r", ruser,
"u", pw->pw_name,
"i", uidstr,
(char *)NULL);
if (result != 1) {
/* skip execution if prior predicate failed */
debug3("%.200s line %d: skipped exec "
"\"%.100s\"", filename, linenum, cmd);
free(cmd);
continue;
}
r = execute_in_shell(cmd);
if (r == -1) {
fatal("%.200s line %d: match exec "
"'%.100s' error", filename,
linenum, cmd);
}
criteria = xstrdup(cmd);
free(cmd);
/* Force exit status to boolean */
r = r == 0;
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else {
error("Unsupported Match attribute %s", attrib);
result = -1;
goto out;
}
debug3("%.200s line %d: %smatched '%s \"%.100s\"' ",
filename, linenum, this_result ? "": "not ",
oattrib, criteria);
free(criteria);
}
if (attributes == 0) {
error("One or more attributes required for Match");
result = -1;
goto out;
}
out:
if (result != -1)
debug2("match %sfound", result ? "" : "not ");
*condition = cp;
free(host);
return result;
}
/* Remove environment variable by pattern */
static void
rm_env(Options *options, const char *arg, const char *filename, int linenum)
{
int i, j;
char *cp;
/* Remove an environment variable */
for (i = 0; i < options->num_send_env; ) {
cp = xstrdup(options->send_env[i]);
if (!match_pattern(cp, arg + 1)) {
free(cp);
i++;
continue;
}
debug3("%s line %d: removing environment %s",
filename, linenum, cp);
free(cp);
free(options->send_env[i]);
options->send_env[i] = NULL;
for (j = i; j < options->num_send_env - 1; j++) {
options->send_env[j] = options->send_env[j + 1];
options->send_env[j + 1] = NULL;
}
options->num_send_env--;
/* NB. don't increment i */
}
}
/*
* Returns the number of the token pointed to by cp or oBadOption.
*/
static OpCodes
parse_token(const char *cp, const char *filename, int linenum,
const char *ignored_unknown)
{
int i;
for (i = 0; keywords[i].name; i++)
if (strcmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
if (ignored_unknown != NULL &&
match_pattern_list(cp, ignored_unknown, 1) == 1)
return oIgnoredUnknownOption;
error("%s: line %d: Bad configuration option: %s",
filename, linenum, cp);
return oBadOption;
}
/* Multistate option parsing */
struct multistate {
char *key;
int value;
};
static const struct multistate multistate_flag[] = {
{ "true", 1 },
{ "false", 0 },
{ "yes", 1 },
{ "no", 0 },
{ NULL, -1 }
};
static const struct multistate multistate_yesnoask[] = {
{ "true", 1 },
{ "false", 0 },
{ "yes", 1 },
{ "no", 0 },
{ "ask", 2 },
{ NULL, -1 }
};
static const struct multistate multistate_strict_hostkey[] = {
{ "true", SSH_STRICT_HOSTKEY_YES },
{ "false", SSH_STRICT_HOSTKEY_OFF },
{ "yes", SSH_STRICT_HOSTKEY_YES },
{ "no", SSH_STRICT_HOSTKEY_OFF },
{ "ask", SSH_STRICT_HOSTKEY_ASK },
{ "off", SSH_STRICT_HOSTKEY_OFF },
{ "accept-new", SSH_STRICT_HOSTKEY_NEW },
{ NULL, -1 }
};
static const struct multistate multistate_yesnoaskconfirm[] = {
{ "true", 1 },
{ "false", 0 },
{ "yes", 1 },
{ "no", 0 },
{ "ask", 2 },
{ "confirm", 3 },
{ NULL, -1 }
};
static const struct multistate multistate_addressfamily[] = {
{ "inet", AF_INET },
{ "inet6", AF_INET6 },
{ "any", AF_UNSPEC },
{ NULL, -1 }
};
static const struct multistate multistate_controlmaster[] = {
{ "true", SSHCTL_MASTER_YES },
{ "yes", SSHCTL_MASTER_YES },
{ "false", SSHCTL_MASTER_NO },
{ "no", SSHCTL_MASTER_NO },
{ "auto", SSHCTL_MASTER_AUTO },
{ "ask", SSHCTL_MASTER_ASK },
{ "autoask", SSHCTL_MASTER_AUTO_ASK },
{ NULL, -1 }
};
static const struct multistate multistate_tunnel[] = {
{ "ethernet", SSH_TUNMODE_ETHERNET },
{ "point-to-point", SSH_TUNMODE_POINTOPOINT },
{ "true", SSH_TUNMODE_DEFAULT },
{ "yes", SSH_TUNMODE_DEFAULT },
{ "false", SSH_TUNMODE_NO },
{ "no", SSH_TUNMODE_NO },
{ NULL, -1 }
};
static const struct multistate multistate_requesttty[] = {
{ "true", REQUEST_TTY_YES },
{ "yes", REQUEST_TTY_YES },
{ "false", REQUEST_TTY_NO },
{ "no", REQUEST_TTY_NO },
{ "force", REQUEST_TTY_FORCE },
{ "auto", REQUEST_TTY_AUTO },
{ NULL, -1 }
};
static const struct multistate multistate_canonicalizehostname[] = {
{ "true", SSH_CANONICALISE_YES },
{ "false", SSH_CANONICALISE_NO },
{ "yes", SSH_CANONICALISE_YES },
{ "no", SSH_CANONICALISE_NO },
{ "always", SSH_CANONICALISE_ALWAYS },
{ NULL, -1 }
};
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set.
*/
int
process_config_line(Options *options, struct passwd *pw, const char *host,
const char *original_host, char *line, const char *filename,
int linenum, int *activep, int flags)
{
return process_config_line_depth(options, pw, host, original_host,
- line, filename, linenum, activep, flags, 0);
+ line, filename, linenum, activep, flags, NULL, 0);
}
#define WHITESPACE " \t\r\n"
static int
process_config_line_depth(Options *options, struct passwd *pw, const char *host,
const char *original_host, char *line, const char *filename,
- int linenum, int *activep, int flags, int depth)
+ int linenum, int *activep, int flags, int *want_final_pass, int depth)
{
char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
char **cpptr, fwdarg[256];
u_int i, *uintptr, max_entries = 0;
int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
int remotefwd, dynamicfwd;
LogLevel *log_level_ptr;
SyslogFacility *log_facility_ptr;
long long val64;
size_t len;
struct Forward fwd;
const struct multistate *multistate_ptr;
struct allowed_cname *cname;
glob_t gl;
const char *errstr;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
activep = &cmdline;
}
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
return 0;
for (len--; len > 0; len--) {
if (strchr(WHITESPACE "\f", line[len]) == NULL)
break;
line[len] = '\0';
}
s = line;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
if ((keyword = strdelim(&s)) == NULL)
return 0;
/* Ignore leading whitespace. */
if (*keyword == '\0')
keyword = strdelim(&s);
if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
return 0;
/* Match lowercase keyword */
lowercase(keyword);
opcode = parse_token(keyword, filename, linenum,
options->ignored_unknown);
switch (opcode) {
case oBadOption:
/* don't panic, but count bad options */
return -1;
case oIgnore:
return 0;
case oIgnoredUnknownOption:
debug("%s line %d: Ignored unknown option \"%s\"",
filename, linenum, keyword);
return 0;
case oConnectTimeout:
intptr = &options->connection_timeout;
parse_time:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
filename, linenum);
if (strcmp(arg, "none") == 0)
value = -1;
else if ((value = convtime(arg)) == -1)
fatal("%s line %d: invalid time value.",
filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oForwardAgent:
intptr = &options->forward_agent;
parse_flag:
multistate_ptr = multistate_flag;
parse_multistate:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%s line %d: missing argument.",
filename, linenum);
value = -1;
for (i = 0; multistate_ptr[i].key != NULL; i++) {
if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
value = multistate_ptr[i].value;
break;
}
}
if (value == -1)
fatal("%s line %d: unsupported option \"%s\".",
filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oForwardX11:
intptr = &options->forward_x11;
goto parse_flag;
case oForwardX11Trusted:
intptr = &options->forward_x11_trusted;
goto parse_flag;
case oForwardX11Timeout:
intptr = &options->forward_x11_timeout;
goto parse_time;
case oGatewayPorts:
intptr = &options->fwd_opts.gateway_ports;
goto parse_flag;
case oExitOnForwardFailure:
intptr = &options->exit_on_forward_failure;
goto parse_flag;
case oPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case oKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
case oKbdInteractiveDevices:
charptr = &options->kbd_interactive_devices;
goto parse_string;
case oPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
case oHostbasedAuthentication:
intptr = &options->hostbased_authentication;
goto parse_flag;
case oChallengeResponseAuthentication:
intptr = &options->challenge_response_authentication;
goto parse_flag;
case oGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
case oGssDelegateCreds:
intptr = &options->gss_deleg_creds;
goto parse_flag;
case oBatchMode:
intptr = &options->batch_mode;
goto parse_flag;
case oCheckHostIP:
intptr = &options->check_host_ip;
goto parse_flag;
case oVerifyHostKeyDNS:
intptr = &options->verify_host_key_dns;
multistate_ptr = multistate_yesnoask;
goto parse_multistate;
case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking;
multistate_ptr = multistate_strict_hostkey;
goto parse_multistate;
case oCompression:
intptr = &options->compression;
goto parse_flag;
case oTCPKeepAlive:
intptr = &options->tcp_keep_alive;
goto parse_flag;
case oNoHostAuthenticationForLocalhost:
intptr = &options->no_host_authentication_for_localhost;
goto parse_flag;
case oNumberOfPasswordPrompts:
intptr = &options->number_of_password_prompts;
goto parse_int;
case oRekeyLimit:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
if (strcmp(arg, "default") == 0) {
val64 = 0;
} else {
if (scan_scaled(arg, &val64) == -1)
fatal("%.200s line %d: Bad number '%s': %s",
filename, linenum, arg, strerror(errno));
if (val64 != 0 && val64 < 16)
fatal("%.200s line %d: RekeyLimit too small",
filename, linenum);
}
if (*activep && options->rekey_limit == -1)
options->rekey_limit = val64;
if (s != NULL) { /* optional rekey interval present */
if (strcmp(s, "none") == 0) {
(void)strdelim(&s); /* discard */
break;
}
intptr = &options->rekey_interval;
goto parse_time;
}
break;
case oIdentityFile:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep) {
intptr = &options->num_identity_files;
if (*intptr >= SSH_MAX_IDENTITY_FILES)
fatal("%.200s line %d: Too many identity files specified (max %d).",
filename, linenum, SSH_MAX_IDENTITY_FILES);
add_identity_file(options, NULL,
arg, flags & SSHCONF_USERCONF);
}
break;
case oCertificateFile:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (*activep) {
intptr = &options->num_certificate_files;
if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
fatal("%.200s line %d: Too many certificate "
"files specified (max %d).",
filename, linenum,
SSH_MAX_CERTIFICATE_FILES);
}
add_certificate_file(options, arg,
flags & SSHCONF_USERCONF);
}
break;
case oXAuthLocation:
charptr=&options->xauth_location;
goto parse_string;
case oUser:
charptr = &options->user;
parse_string:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case oGlobalKnownHostsFile:
cpptr = (char **)&options->system_hostfiles;
uintptr = &options->num_system_hostfiles;
max_entries = SSH_MAX_HOSTS_FILES;
parse_char_array:
if (*activep && *uintptr == 0) {
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
if ((*uintptr) >= max_entries)
fatal("%s line %d: "
"too many authorized keys files.",
filename, linenum);
cpptr[(*uintptr)++] = xstrdup(arg);
}
}
return 0;
case oUserKnownHostsFile:
cpptr = (char **)&options->user_hostfiles;
uintptr = &options->num_user_hostfiles;
max_entries = SSH_MAX_HOSTS_FILES;
goto parse_char_array;
case oHostName:
charptr = &options->hostname;
goto parse_string;
case oHostKeyAlias:
charptr = &options->host_key_alias;
goto parse_string;
case oPreferredAuthentications:
charptr = &options->preferred_authentications;
goto parse_string;
case oBindAddress:
charptr = &options->bind_address;
goto parse_string;
case oBindInterface:
charptr = &options->bind_interface;
goto parse_string;
case oPKCS11Provider:
charptr = &options->pkcs11_provider;
goto parse_string;
case oProxyCommand:
charptr = &options->proxy_command;
/* Ignore ProxyCommand if ProxyJump already specified */
if (options->jump_host != NULL)
charptr = &options->jump_host; /* Skip below */
parse_command:
if (s == NULL)
fatal("%.200s line %d: Missing argument.", filename, linenum);
len = strspn(s, WHITESPACE "=");
if (*activep && *charptr == NULL)
*charptr = xstrdup(s + len);
return 0;
case oProxyJump:
if (s == NULL) {
fatal("%.200s line %d: Missing argument.",
filename, linenum);
}
len = strspn(s, WHITESPACE "=");
if (parse_jump(s + len, options, *activep) == -1) {
fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
filename, linenum, s + len);
}
return 0;
case oPort:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
value = a2port(arg);
if (value <= 0)
fatal("%.200s line %d: Bad port '%s'.",
filename, linenum, arg);
if (*activep && options->port == -1)
options->port = value;
break;
case oConnectionAttempts:
intptr = &options->connection_attempts;
parse_int:
arg = strdelim(&s);
if ((errstr = atoi_err(arg, &value)) != NULL)
fatal("%s line %d: integer value %s.",
filename, linenum, errstr);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oCiphers:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case oMacs:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->macs == NULL)
options->macs = xstrdup(arg);
break;
case oKexAlgorithms:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (*arg != '-' &&
!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
case oHostKeyAlgorithms:
charptr = &options->hostkeyalgorithms;
parse_keytypes:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (*arg != '-' &&
!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case oCASignatureAlgorithms:
charptr = &options->ca_sign_algorithms;
goto parse_keytypes;
case oLogLevel:
log_level_ptr = &options->log_level;
arg = strdelim(&s);
value = log_level_number(arg);
if (value == SYSLOG_LEVEL_NOT_SET)
fatal("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
*log_level_ptr = (LogLevel) value;
break;
case oLogFacility:
log_facility_ptr = &options->log_facility;
arg = strdelim(&s);
value = log_facility_number(arg);
if (value == SYSLOG_FACILITY_NOT_SET)
fatal("%.200s line %d: unsupported log facility '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*log_facility_ptr == -1)
*log_facility_ptr = (SyslogFacility) value;
break;
case oLocalForward:
case oRemoteForward:
case oDynamicForward:
arg = strdelim(&s);
if (arg == NULL || *arg == '\0')
fatal("%.200s line %d: Missing port argument.",
filename, linenum);
remotefwd = (opcode == oRemoteForward);
dynamicfwd = (opcode == oDynamicForward);
if (!dynamicfwd) {
arg2 = strdelim(&s);
if (arg2 == NULL || *arg2 == '\0') {
if (remotefwd)
dynamicfwd = 1;
else
fatal("%.200s line %d: Missing target "
"argument.", filename, linenum);
} else {
/* construct a string for parse_forward */
snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
arg2);
}
}
if (dynamicfwd)
strlcpy(fwdarg, arg, sizeof(fwdarg));
if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
fatal("%.200s line %d: Bad forwarding specification.",
filename, linenum);
if (*activep) {
if (remotefwd) {
add_remote_forward(options, &fwd);
} else {
add_local_forward(options, &fwd);
}
}
break;
case oClearAllForwardings:
intptr = &options->clear_forwardings;
goto parse_flag;
case oHost:
if (cmdline)
fatal("Host directive not supported as a command-line "
"option");
*activep = 0;
arg2 = NULL;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
if ((flags & SSHCONF_NEVERMATCH) != 0)
break;
negated = *arg == '!';
if (negated)
arg++;
if (match_pattern(host, arg)) {
if (negated) {
debug("%.200s line %d: Skipping Host "
"block because of negated match "
"for %.100s", filename, linenum,
arg);
*activep = 0;
break;
}
if (!*activep)
arg2 = arg; /* logged below */
*activep = 1;
}
}
if (*activep)
debug("%.200s line %d: Applying options for %.100s",
filename, linenum, arg2);
/* Avoid garbage check below, as strdelim is done. */
return 0;
case oMatch:
if (cmdline)
fatal("Host directive not supported as a command-line "
"option");
value = match_cfg_line(options, &s, pw, host, original_host,
- flags & SSHCONF_POSTCANON, filename, linenum);
+ flags & SSHCONF_FINAL, want_final_pass,
+ filename, linenum);
if (value < 0)
fatal("%.200s line %d: Bad Match condition", filename,
linenum);
*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
break;
case oEscapeChar:
intptr = &options->escape_char;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (strcmp(arg, "none") == 0)
value = SSH_ESCAPECHAR_NONE;
else if (arg[1] == '\0')
value = (u_char) arg[0];
else if (arg[0] == '^' && arg[2] == 0 &&
(u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
value = (u_char) arg[1] & 31;
else {
fatal("%.200s line %d: Bad escape character.",
filename, linenum);
/* NOTREACHED */
value = 0; /* Avoid compiler warning. */
}
if (*activep && *intptr == -1)
*intptr = value;
break;
case oAddressFamily:
intptr = &options->address_family;
multistate_ptr = multistate_addressfamily;
goto parse_multistate;
case oEnableSSHKeysign:
intptr = &options->enable_ssh_keysign;
goto parse_flag;
case oIdentitiesOnly:
intptr = &options->identities_only;
goto parse_flag;
case oServerAliveInterval:
intptr = &options->server_alive_interval;
goto parse_time;
case oServerAliveCountMax:
intptr = &options->server_alive_count_max;
goto parse_int;
case oSendEnv:
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
if (strchr(arg, '=') != NULL)
fatal("%s line %d: Invalid environment name.",
filename, linenum);
if (!*activep)
continue;
if (*arg == '-') {
/* Removing an env var */
rm_env(options, arg, filename, linenum);
continue;
} else {
/* Adding an env var */
if (options->num_send_env >= INT_MAX)
fatal("%s line %d: too many send env.",
filename, linenum);
options->send_env = xrecallocarray(
options->send_env, options->num_send_env,
options->num_send_env + 1,
sizeof(*options->send_env));
options->send_env[options->num_send_env++] =
xstrdup(arg);
}
}
break;
case oSetEnv:
value = options->num_setenv;
while ((arg = strdelimw(&s)) != NULL && *arg != '\0') {
if (strchr(arg, '=') == NULL)
fatal("%s line %d: Invalid SetEnv.",
filename, linenum);
if (!*activep || value != 0)
continue;
/* Adding a setenv var */
if (options->num_setenv >= INT_MAX)
fatal("%s line %d: too many SetEnv.",
filename, linenum);
options->setenv = xrecallocarray(
options->setenv, options->num_setenv,
options->num_setenv + 1, sizeof(*options->setenv));
options->setenv[options->num_setenv++] = xstrdup(arg);
}
break;
case oControlPath:
charptr = &options->control_path;
goto parse_string;
case oControlMaster:
intptr = &options->control_master;
multistate_ptr = multistate_controlmaster;
goto parse_multistate;
case oControlPersist:
/* no/false/yes/true, or a time spec */
intptr = &options->control_persist;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing ControlPersist"
" argument.", filename, linenum);
value = 0;
value2 = 0; /* timeout */
if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
value = 0;
else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
value = 1;
else if ((value2 = convtime(arg)) >= 0)
value = 1;
else
fatal("%.200s line %d: Bad ControlPersist argument.",
filename, linenum);
if (*activep && *intptr == -1) {
*intptr = value;
options->control_persist_timeout = value2;
}
break;
case oHashKnownHosts:
intptr = &options->hash_known_hosts;
goto parse_flag;
case oTunnel:
intptr = &options->tun_open;
multistate_ptr = multistate_tunnel;
goto parse_multistate;
case oTunnelDevice:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename, linenum);
value = a2tun(arg, &value2);
if (value == SSH_TUNID_ERR)
fatal("%.200s line %d: Bad tun device.", filename, linenum);
if (*activep) {
options->tun_local = value;
options->tun_remote = value2;
}
break;
case oLocalCommand:
charptr = &options->local_command;
goto parse_command;
case oPermitLocalCommand:
intptr = &options->permit_local_command;
goto parse_flag;
case oRemoteCommand:
charptr = &options->remote_command;
goto parse_command;
case oVisualHostKey:
intptr = &options->visual_host_key;
goto parse_flag;
case oInclude:
if (cmdline)
fatal("Include directive not supported as a "
"command-line option");
value = 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
/*
* Ensure all paths are anchored. User configuration
* files may begin with '~/' but system configurations
* must not. If the path is relative, then treat it
* as living in ~/.ssh for user configurations or
* /etc/ssh for system ones.
*/
if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
fatal("%.200s line %d: bad include path %s.",
filename, linenum, arg);
- if (*arg != '/' && *arg != '~') {
+ if (!path_absolute(arg) && *arg != '~') {
xasprintf(&arg2, "%s/%s",
(flags & SSHCONF_USERCONF) ?
"~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
} else
arg2 = xstrdup(arg);
memset(&gl, 0, sizeof(gl));
r = glob(arg2, GLOB_TILDE, NULL, &gl);
if (r == GLOB_NOMATCH) {
debug("%.200s line %d: include %s matched no "
"files",filename, linenum, arg2);
free(arg2);
continue;
} else if (r != 0 || gl.gl_pathc < 0)
fatal("%.200s line %d: glob failed for %s.",
filename, linenum, arg2);
free(arg2);
oactive = *activep;
for (i = 0; i < (u_int)gl.gl_pathc; i++) {
debug3("%.200s line %d: Including file %s "
"depth %d%s", filename, linenum,
gl.gl_pathv[i], depth,
oactive ? "" : " (parse only)");
r = read_config_file_depth(gl.gl_pathv[i],
pw, host, original_host, options,
flags | SSHCONF_CHECKPERM |
(oactive ? 0 : SSHCONF_NEVERMATCH),
- activep, depth + 1);
+ activep, want_final_pass, depth + 1);
if (r != 1 && errno != ENOENT) {
fatal("Can't open user config file "
"%.100s: %.100s", gl.gl_pathv[i],
strerror(errno));
}
/*
* don't let Match in includes clobber the
* containing file's Match state.
*/
*activep = oactive;
if (r != 1)
value = -1;
}
globfree(&gl);
}
if (value != 0)
return value;
break;
case oIPQoS:
arg = strdelim(&s);
if ((value = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
arg = strdelim(&s);
if (arg == NULL)
value2 = value;
else if ((value2 = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
if (*activep) {
options->ip_qos_interactive = value;
options->ip_qos_bulk = value2;
}
break;
case oRequestTTY:
intptr = &options->request_tty;
multistate_ptr = multistate_requesttty;
goto parse_multistate;
case oIgnoreUnknown:
charptr = &options->ignored_unknown;
goto parse_string;
case oProxyUseFdpass:
intptr = &options->proxy_use_fdpass;
goto parse_flag;
case oCanonicalDomains:
value = options->num_canonical_domains != 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
if (!valid_domain(arg, 1, &errstr)) {
fatal("%s line %d: %s", filename, linenum,
errstr);
}
if (!*activep || value)
continue;
if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
fatal("%s line %d: too many hostname suffixes.",
filename, linenum);
options->canonical_domains[
options->num_canonical_domains++] = xstrdup(arg);
}
break;
case oCanonicalizePermittedCNAMEs:
value = options->num_permitted_cnames != 0;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
/* Either '*' for everything or 'list:list' */
if (strcmp(arg, "*") == 0)
arg2 = arg;
else {
lowercase(arg);
if ((arg2 = strchr(arg, ':')) == NULL ||
arg2[1] == '\0') {
fatal("%s line %d: "
"Invalid permitted CNAME \"%s\"",
filename, linenum, arg);
}
*arg2 = '\0';
arg2++;
}
if (!*activep || value)
continue;
if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
fatal("%s line %d: too many permitted CNAMEs.",
filename, linenum);
cname = options->permitted_cnames +
options->num_permitted_cnames++;
cname->source_list = xstrdup(arg);
cname->target_list = xstrdup(arg2);
}
break;
case oCanonicalizeHostname:
intptr = &options->canonicalize_hostname;
multistate_ptr = multistate_canonicalizehostname;
goto parse_multistate;
case oCanonicalizeMaxDots:
intptr = &options->canonicalize_max_dots;
goto parse_int;
case oCanonicalizeFallbackLocal:
intptr = &options->canonicalize_fallback_local;
goto parse_flag;
case oStreamLocalBindMask:
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
/* Parse mode in octal format */
value = strtol(arg, &endofnumber, 8);
if (arg == endofnumber || value < 0 || value > 0777)
fatal("%.200s line %d: Bad mask.", filename, linenum);
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
case oStreamLocalBindUnlink:
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
case oRevokedHostKeys:
charptr = &options->revoked_host_keys;
goto parse_string;
case oFingerprintHash:
intptr = &options->fingerprint_hash;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if ((value = ssh_digest_alg_by_name(arg)) == -1)
fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case oUpdateHostkeys:
intptr = &options->update_hostkeys;
multistate_ptr = multistate_yesnoask;
goto parse_multistate;
case oHostbasedKeyTypes:
charptr = &options->hostbased_key_types;
goto parse_keytypes;
case oPubkeyAcceptedKeyTypes:
charptr = &options->pubkey_key_types;
goto parse_keytypes;
case oAddKeysToAgent:
intptr = &options->add_keys_to_agent;
multistate_ptr = multistate_yesnoaskconfirm;
goto parse_multistate;
case oIdentityAgent:
charptr = &options->identity_agent;
arg = strdelim(&s);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
/* Extra validation if the string represents an env var. */
if (arg[0] == '$' && !valid_env_name(arg + 1)) {
fatal("%.200s line %d: Invalid environment name %s.",
filename, linenum, arg);
}
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
return 0;
case oUnsupported:
error("%s line %d: Unsupported option \"%s\"",
filename, linenum, keyword);
return 0;
default:
fatal("%s: Unimplemented opcode %d", __func__, opcode);
}
/* Check that there is no garbage at end of line. */
if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
}
return 0;
}
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns 0.
*/
int
read_config_file(const char *filename, struct passwd *pw, const char *host,
- const char *original_host, Options *options, int flags)
+ const char *original_host, Options *options, int flags,
+ int *want_final_pass)
{
int active = 1;
return read_config_file_depth(filename, pw, host, original_host,
- options, flags, &active, 0);
+ options, flags, &active, want_final_pass, 0);
}
#define READCONF_MAX_DEPTH 16
static int
read_config_file_depth(const char *filename, struct passwd *pw,
const char *host, const char *original_host, Options *options,
- int flags, int *activep, int depth)
+ int flags, int *activep, int *want_final_pass, int depth)
{
FILE *f;
char *line = NULL;
size_t linesize = 0;
int linenum;
int bad_options = 0;
if (depth < 0 || depth > READCONF_MAX_DEPTH)
fatal("Too many recursive configuration includes");
if ((f = fopen(filename, "r")) == NULL)
return 0;
if (flags & SSHCONF_CHECKPERM) {
struct stat sb;
if (fstat(fileno(f), &sb) == -1)
fatal("fstat %s: %s", filename, strerror(errno));
if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
(sb.st_mode & 022) != 0))
fatal("Bad owner or permissions on %s", filename);
}
debug("Reading configuration data %.200s", filename);
/*
* Mark that we are now processing the options. This flag is turned
* on/off by Host specifications.
*/
linenum = 0;
while (getline(&line, &linesize, f) != -1) {
/* Update line number counter. */
linenum++;
if (process_config_line_depth(options, pw, host, original_host,
- line, filename, linenum, activep, flags, depth) != 0)
+ line, filename, linenum, activep, flags, want_final_pass,
+ depth) != 0)
bad_options++;
}
free(line);
fclose(f);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);
return 1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
int
option_clear_or_none(const char *o)
{
return o == NULL || strcasecmp(o, "none") == 0;
}
/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
* are processed in the following order: command line, user config file,
* system config file. Last, fill_default_options is called.
*/
void
initialize_options(Options * options)
{
memset(options, 'X', sizeof(*options));
options->forward_agent = -1;
options->forward_x11 = -1;
options->forward_x11_trusted = -1;
options->forward_x11_timeout = -1;
options->stdio_forward_host = NULL;
options->stdio_forward_port = 0;
options->clear_forwardings = -1;
options->exit_on_forward_failure = -1;
options->xauth_location = NULL;
options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
options->pubkey_authentication = -1;
options->challenge_response_authentication = -1;
options->gss_authentication = -1;
options->gss_deleg_creds = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->kbd_interactive_devices = NULL;
options->hostbased_authentication = -1;
options->batch_mode = -1;
options->check_host_ip = -1;
options->strict_host_key_checking = -1;
options->compression = -1;
options->tcp_keep_alive = -1;
options->port = -1;
options->address_family = -1;
options->connection_attempts = -1;
options->connection_timeout = -1;
options->number_of_password_prompts = -1;
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
options->hostkeyalgorithms = NULL;
options->ca_sign_algorithms = NULL;
options->num_identity_files = 0;
options->num_certificate_files = 0;
options->hostname = NULL;
options->host_key_alias = NULL;
options->proxy_command = NULL;
options->jump_user = NULL;
options->jump_host = NULL;
options->jump_port = -1;
options->jump_extra = NULL;
options->user = NULL;
options->escape_char = -1;
options->num_system_hostfiles = 0;
options->num_user_hostfiles = 0;
options->local_forwards = NULL;
options->num_local_forwards = 0;
options->remote_forwards = NULL;
options->num_remote_forwards = 0;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
options->preferred_authentications = NULL;
options->bind_address = NULL;
options->bind_interface = NULL;
options->pkcs11_provider = NULL;
options->enable_ssh_keysign = - 1;
options->no_host_authentication_for_localhost = - 1;
options->identities_only = - 1;
options->rekey_limit = - 1;
options->rekey_interval = -1;
options->verify_host_key_dns = -1;
options->server_alive_interval = -1;
options->server_alive_count_max = -1;
options->send_env = NULL;
options->num_send_env = 0;
options->setenv = NULL;
options->num_setenv = 0;
options->control_path = NULL;
options->control_master = -1;
options->control_persist = -1;
options->control_persist_timeout = 0;
options->hash_known_hosts = -1;
options->tun_open = -1;
options->tun_local = -1;
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
options->remote_command = NULL;
options->add_keys_to_agent = -1;
options->identity_agent = NULL;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->request_tty = -1;
options->proxy_use_fdpass = -1;
options->ignored_unknown = NULL;
options->num_canonical_domains = 0;
options->num_permitted_cnames = 0;
options->canonicalize_max_dots = -1;
options->canonicalize_fallback_local = -1;
options->canonicalize_hostname = -1;
options->revoked_host_keys = NULL;
options->fingerprint_hash = -1;
options->update_hostkeys = -1;
options->hostbased_key_types = NULL;
options->pubkey_key_types = NULL;
}
/*
* A petite version of fill_default_options() that just fills the options
* needed for hostname canonicalization to proceed.
*/
void
fill_default_options_for_canonicalization(Options *options)
{
if (options->canonicalize_max_dots == -1)
options->canonicalize_max_dots = 1;
if (options->canonicalize_fallback_local == -1)
options->canonicalize_fallback_local = 1;
if (options->canonicalize_hostname == -1)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
}
/*
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
void
fill_default_options(Options * options)
{
char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
int r;
if (options->forward_agent == -1)
options->forward_agent = 0;
if (options->forward_x11 == -1)
options->forward_x11 = 0;
if (options->forward_x11_trusted == -1)
options->forward_x11_trusted = 0;
if (options->forward_x11_timeout == -1)
options->forward_x11_timeout = 1200;
/*
* stdio forwarding (-W) changes the default for these but we defer
* setting the values so they can be overridden.
*/
if (options->exit_on_forward_failure == -1)
options->exit_on_forward_failure =
options->stdio_forward_host != NULL ? 1 : 0;
if (options->clear_forwardings == -1)
options->clear_forwardings =
options->stdio_forward_host != NULL ? 1 : 0;
if (options->clear_forwardings == 1)
clear_forwardings(options);
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
if (options->fwd_opts.gateway_ports == -1)
options->fwd_opts.gateway_ports = 0;
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_deleg_creds == -1)
options->gss_deleg_creds = 0;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 1;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->batch_mode == -1)
options->batch_mode = 0;
if (options->check_host_ip == -1)
options->check_host_ip = 1;
if (options->strict_host_key_checking == -1)
options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
if (options->compression == -1)
options->compression = 0;
if (options->tcp_keep_alive == -1)
options->tcp_keep_alive = 1;
if (options->port == -1)
options->port = 0; /* Filled in ssh_connect. */
if (options->address_family == -1)
options->address_family = AF_UNSPEC;
if (options->connection_attempts == -1)
options->connection_attempts = 1;
if (options->number_of_password_prompts == -1)
options->number_of_password_prompts = 3;
/* options->hostkeyalgorithms, default set in myproposals.h */
if (options->add_keys_to_agent == -1)
options->add_keys_to_agent = 0;
if (options->num_identity_files == 0) {
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
#ifdef OPENSSL_HAS_ECC
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
#endif
add_identity_file(options, "~/",
_PATH_SSH_CLIENT_ID_ED25519, 0);
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
}
if (options->escape_char == -1)
options->escape_char = '~';
if (options->num_system_hostfiles == 0) {
options->system_hostfiles[options->num_system_hostfiles++] =
xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
options->system_hostfiles[options->num_system_hostfiles++] =
xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
}
if (options->num_user_hostfiles == 0) {
options->user_hostfiles[options->num_user_hostfiles++] =
xstrdup(_PATH_SSH_USER_HOSTFILE);
options->user_hostfiles[options->num_user_hostfiles++] =
xstrdup(_PATH_SSH_USER_HOSTFILE2);
}
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
options->log_facility = SYSLOG_FACILITY_USER;
if (options->no_host_authentication_for_localhost == - 1)
options->no_host_authentication_for_localhost = 0;
if (options->identities_only == -1)
options->identities_only = 0;
if (options->enable_ssh_keysign == -1)
options->enable_ssh_keysign = 0;
if (options->rekey_limit == -1)
options->rekey_limit = 0;
if (options->rekey_interval == -1)
options->rekey_interval = 0;
if (options->verify_host_key_dns == -1)
options->verify_host_key_dns = 0;
if (options->server_alive_interval == -1)
options->server_alive_interval = 0;
if (options->server_alive_count_max == -1)
options->server_alive_count_max = 3;
if (options->control_master == -1)
options->control_master = 0;
if (options->control_persist == -1) {
options->control_persist = 0;
options->control_persist_timeout = 0;
}
if (options->hash_known_hosts == -1)
options->hash_known_hosts = 0;
if (options->tun_open == -1)
options->tun_open = SSH_TUNMODE_NO;
if (options->tun_local == -1)
options->tun_local = SSH_TUNID_ANY;
if (options->tun_remote == -1)
options->tun_remote = SSH_TUNID_ANY;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
if (options->visual_host_key == -1)
options->visual_host_key = 0;
if (options->ip_qos_interactive == -1)
options->ip_qos_interactive = IPTOS_DSCP_AF21;
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_DSCP_CS1;
if (options->request_tty == -1)
options->request_tty = REQUEST_TTY_AUTO;
if (options->proxy_use_fdpass == -1)
options->proxy_use_fdpass = 0;
if (options->canonicalize_max_dots == -1)
options->canonicalize_max_dots = 1;
if (options->canonicalize_fallback_local == -1)
options->canonicalize_fallback_local = 1;
if (options->canonicalize_hostname == -1)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
if (options->update_hostkeys == -1)
options->update_hostkeys = 0;
/* Expand KEX name lists */
all_cipher = cipher_alg_list(',', 0);
all_mac = mac_alg_list(',');
all_kex = kex_alg_list(',');
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&options->what, \
defaults, all)) != 0) \
fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
} while (0)
- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
+ ASSEMBLE(ciphers, KEX_CLIENT_ENCRYPT, all_cipher);
+ ASSEMBLE(macs, KEX_CLIENT_MAC, all_mac);
+ ASSEMBLE(kex_algorithms, KEX_CLIENT_KEX, all_kex);
ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
#undef ASSEMBLE
free(all_cipher);
free(all_mac);
free(all_kex);
free(all_key);
free(all_sig);
#define CLEAR_ON_NONE(v) \
do { \
if (option_clear_or_none(v)) { \
free(v); \
v = NULL; \
} \
} while(0)
CLEAR_ON_NONE(options->local_command);
CLEAR_ON_NONE(options->remote_command);
CLEAR_ON_NONE(options->proxy_command);
CLEAR_ON_NONE(options->control_path);
CLEAR_ON_NONE(options->revoked_host_keys);
+ CLEAR_ON_NONE(options->pkcs11_provider);
if (options->jump_host != NULL &&
strcmp(options->jump_host, "none") == 0 &&
options->jump_port == 0 && options->jump_user == NULL) {
free(options->jump_host);
options->jump_host = NULL;
}
/* options->identity_agent distinguishes NULL from 'none' */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
/* options->host_key_alias should not be set by default */
/* options->preferred_authentications will be set in ssh */
}
struct fwdarg {
char *arg;
int ispath;
};
/*
* parse_fwd_field
* parses the next field in a port forwarding specification.
* sets fwd to the parsed field and advances p past the colon
* or sets it to NULL at end of string.
* returns 0 on success, else non-zero.
*/
static int
parse_fwd_field(char **p, struct fwdarg *fwd)
{
char *ep, *cp = *p;
int ispath = 0;
if (*cp == '\0') {
*p = NULL;
return -1; /* end of string */
}
/*
* A field escaped with square brackets is used literally.
* XXX - allow ']' to be escaped via backslash?
*/
if (*cp == '[') {
/* find matching ']' */
for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
if (*ep == '/')
ispath = 1;
}
/* no matching ']' or not at end of field. */
if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
return -1;
/* NUL terminate the field and advance p past the colon */
*ep++ = '\0';
if (*ep != '\0')
*ep++ = '\0';
fwd->arg = cp + 1;
fwd->ispath = ispath;
*p = ep;
return 0;
}
for (cp = *p; *cp != '\0'; cp++) {
switch (*cp) {
case '\\':
memmove(cp, cp + 1, strlen(cp + 1) + 1);
if (*cp == '\0')
return -1;
break;
case '/':
ispath = 1;
break;
case ':':
*cp++ = '\0';
goto done;
}
}
done:
fwd->arg = *p;
fwd->ispath = ispath;
*p = cp;
return 0;
}
/*
* parse_forward
* parses a string containing a port forwarding specification of the form:
* dynamicfwd == 0
* [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
* listenpath:connectpath
* dynamicfwd == 1
* [listenhost:]listenport
* returns number of arguments parsed or zero on error
*/
int
parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
{
struct fwdarg fwdargs[4];
char *p, *cp;
int i;
memset(fwd, 0, sizeof(*fwd));
memset(fwdargs, 0, sizeof(fwdargs));
cp = p = xstrdup(fwdspec);
/* skip leading spaces */
while (isspace((u_char)*cp))
cp++;
for (i = 0; i < 4; ++i) {
if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
break;
}
/* Check for trailing garbage */
if (cp != NULL && *cp != '\0') {
i = 0; /* failure */
}
switch (i) {
case 1:
if (fwdargs[0].ispath) {
fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->listen_port = PORT_STREAMLOCAL;
} else {
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdargs[0].arg);
}
fwd->connect_host = xstrdup("socks");
break;
case 2:
if (fwdargs[0].ispath && fwdargs[1].ispath) {
fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->listen_port = PORT_STREAMLOCAL;
fwd->connect_path = xstrdup(fwdargs[1].arg);
fwd->connect_port = PORT_STREAMLOCAL;
} else if (fwdargs[1].ispath) {
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdargs[0].arg);
fwd->connect_path = xstrdup(fwdargs[1].arg);
fwd->connect_port = PORT_STREAMLOCAL;
} else {
fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_host = xstrdup("socks");
}
break;
case 3:
if (fwdargs[0].ispath) {
fwd->listen_path = xstrdup(fwdargs[0].arg);
fwd->listen_port = PORT_STREAMLOCAL;
fwd->connect_host = xstrdup(fwdargs[1].arg);
fwd->connect_port = a2port(fwdargs[2].arg);
} else if (fwdargs[2].ispath) {
fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_path = xstrdup(fwdargs[2].arg);
fwd->connect_port = PORT_STREAMLOCAL;
} else {
fwd->listen_host = NULL;
fwd->listen_port = a2port(fwdargs[0].arg);
fwd->connect_host = xstrdup(fwdargs[1].arg);
fwd->connect_port = a2port(fwdargs[2].arg);
}
break;
case 4:
fwd->listen_host = xstrdup(fwdargs[0].arg);
fwd->listen_port = a2port(fwdargs[1].arg);
fwd->connect_host = xstrdup(fwdargs[2].arg);
fwd->connect_port = a2port(fwdargs[3].arg);
break;
default:
i = 0; /* failure */
}
free(p);
if (dynamicfwd) {
if (!(i == 1 || i == 2))
goto fail_free;
} else {
if (!(i == 3 || i == 4)) {
if (fwd->connect_path == NULL &&
fwd->listen_path == NULL)
goto fail_free;
}
if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
goto fail_free;
}
if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
(!remotefwd && fwd->listen_port == 0))
goto fail_free;
if (fwd->connect_host != NULL &&
strlen(fwd->connect_host) >= NI_MAXHOST)
goto fail_free;
/* XXX - if connecting to a remote socket, max sun len may not match this host */
if (fwd->connect_path != NULL &&
strlen(fwd->connect_path) >= PATH_MAX_SUN)
goto fail_free;
if (fwd->listen_host != NULL &&
strlen(fwd->listen_host) >= NI_MAXHOST)
goto fail_free;
if (fwd->listen_path != NULL &&
strlen(fwd->listen_path) >= PATH_MAX_SUN)
goto fail_free;
return (i);
fail_free:
free(fwd->connect_host);
fwd->connect_host = NULL;
free(fwd->connect_path);
fwd->connect_path = NULL;
free(fwd->listen_host);
fwd->listen_host = NULL;
free(fwd->listen_path);
fwd->listen_path = NULL;
return (0);
}
int
parse_jump(const char *s, Options *o, int active)
{
char *orig, *sdup, *cp;
char *host = NULL, *user = NULL;
int ret = -1, port = -1, first;
active &= o->proxy_command == NULL && o->jump_host == NULL;
orig = sdup = xstrdup(s);
first = active;
do {
if (strcasecmp(s, "none") == 0)
break;
if ((cp = strrchr(sdup, ',')) == NULL)
cp = sdup; /* last */
else
*cp++ = '\0';
if (first) {
/* First argument and configuration is active */
if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
parse_user_host_port(cp, &user, &host, &port) != 0)
goto out;
} else {
/* Subsequent argument or inactive configuration */
if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
parse_user_host_port(cp, NULL, NULL, NULL) != 0)
goto out;
}
first = 0; /* only check syntax for subsequent hosts */
} while (cp != sdup);
/* success */
if (active) {
if (strcasecmp(s, "none") == 0) {
o->jump_host = xstrdup("none");
o->jump_port = 0;
} else {
o->jump_user = user;
o->jump_host = host;
o->jump_port = port;
o->proxy_command = xstrdup("none");
user = host = NULL;
if ((cp = strrchr(s, ',')) != NULL && cp != s) {
o->jump_extra = xstrdup(s);
o->jump_extra[cp - s] = '\0';
}
}
}
ret = 0;
out:
free(orig);
free(user);
free(host);
return ret;
}
int
parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
{
char *path;
int r;
r = parse_uri("ssh", uri, userp, hostp, portp, &path);
if (r == 0 && path != NULL)
r = -1; /* path not allowed */
return r;
}
/* XXX the following is a near-vebatim copy from servconf.c; refactor */
static const char *
fmt_multistate_int(int val, const struct multistate *m)
{
u_int i;
for (i = 0; m[i].key != NULL; i++) {
if (m[i].value == val)
return m[i].key;
}
return "UNKNOWN";
}
static const char *
fmt_intarg(OpCodes code, int val)
{
if (val == -1)
return "unset";
switch (code) {
case oAddressFamily:
return fmt_multistate_int(val, multistate_addressfamily);
case oVerifyHostKeyDNS:
case oUpdateHostkeys:
return fmt_multistate_int(val, multistate_yesnoask);
case oStrictHostKeyChecking:
return fmt_multistate_int(val, multistate_strict_hostkey);
case oControlMaster:
return fmt_multistate_int(val, multistate_controlmaster);
case oTunnel:
return fmt_multistate_int(val, multistate_tunnel);
case oRequestTTY:
return fmt_multistate_int(val, multistate_requesttty);
case oCanonicalizeHostname:
return fmt_multistate_int(val, multistate_canonicalizehostname);
case oAddKeysToAgent:
return fmt_multistate_int(val, multistate_yesnoaskconfirm);
case oFingerprintHash:
return ssh_digest_alg_name(val);
default:
switch (val) {
case 0:
return "no";
case 1:
return "yes";
default:
return "UNKNOWN";
}
}
}
static const char *
lookup_opcode_name(OpCodes code)
{
u_int i;
for (i = 0; keywords[i].name != NULL; i++)
if (keywords[i].opcode == code)
return(keywords[i].name);
return "UNKNOWN";
}
static void
dump_cfg_int(OpCodes code, int val)
{
printf("%s %d\n", lookup_opcode_name(code), val);
}
static void
dump_cfg_fmtint(OpCodes code, int val)
{
printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
}
static void
dump_cfg_string(OpCodes code, const char *val)
{
if (val == NULL)
return;
printf("%s %s\n", lookup_opcode_name(code), val);
}
static void
dump_cfg_strarray(OpCodes code, u_int count, char **vals)
{
u_int i;
for (i = 0; i < count; i++)
printf("%s %s\n", lookup_opcode_name(code), vals[i]);
}
static void
dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
{
u_int i;
printf("%s", lookup_opcode_name(code));
for (i = 0; i < count; i++)
printf(" %s", vals[i]);
printf("\n");
}
static void
dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
{
const struct Forward *fwd;
u_int i;
/* oDynamicForward */
for (i = 0; i < count; i++) {
fwd = &fwds[i];
if (code == oDynamicForward && fwd->connect_host != NULL &&
strcmp(fwd->connect_host, "socks") != 0)
continue;
if (code == oLocalForward && fwd->connect_host != NULL &&
strcmp(fwd->connect_host, "socks") == 0)
continue;
printf("%s", lookup_opcode_name(code));
if (fwd->listen_port == PORT_STREAMLOCAL)
printf(" %s", fwd->listen_path);
else if (fwd->listen_host == NULL)
printf(" %d", fwd->listen_port);
else {
printf(" [%s]:%d",
fwd->listen_host, fwd->listen_port);
}
if (code != oDynamicForward) {
if (fwd->connect_port == PORT_STREAMLOCAL)
printf(" %s", fwd->connect_path);
else if (fwd->connect_host == NULL)
printf(" %d", fwd->connect_port);
else {
printf(" [%s]:%d",
fwd->connect_host, fwd->connect_port);
}
}
printf("\n");
}
}
void
dump_client_config(Options *o, const char *host)
{
int i;
char buf[8], *all_key;
/* This is normally prepared in ssh_kex2 */
all_key = sshkey_alg_list(0, 0, 1, ',');
if (kex_assemble_names( &o->hostkeyalgorithms,
KEX_DEFAULT_PK_ALG, all_key) != 0)
fatal("%s: kex_assemble_names failed", __func__);
free(all_key);
/* Most interesting options first: user, host, port */
dump_cfg_string(oUser, o->user);
dump_cfg_string(oHostName, host);
dump_cfg_int(oPort, o->port);
/* Flag options */
dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
dump_cfg_fmtint(oAddressFamily, o->address_family);
dump_cfg_fmtint(oBatchMode, o->batch_mode);
dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
dump_cfg_fmtint(oCompression, o->compression);
dump_cfg_fmtint(oControlMaster, o->control_master);
dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(oForwardAgent, o->forward_agent);
dump_cfg_fmtint(oForwardX11, o->forward_x11);
dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
#ifdef GSSAPI
dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
#endif /* GSSAPI */
dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
dump_cfg_fmtint(oRequestTTY, o->request_tty);
dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
dump_cfg_fmtint(oTunnel, o->tun_open);
dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
/* Integer options */
dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
dump_cfg_int(oConnectionAttempts, o->connection_attempts);
dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
/* String options */
dump_cfg_string(oBindAddress, o->bind_address);
dump_cfg_string(oBindInterface, o->bind_interface);
dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
dump_cfg_string(oControlPath, o->control_path);
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
dump_cfg_string(oHostKeyAlias, o->host_key_alias);
dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
dump_cfg_string(oIdentityAgent, o->identity_agent);
dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms ? o->ca_sign_algorithms : SSH_ALLOWED_CA_SIGALGS);
dump_cfg_string(oLocalCommand, o->local_command);
dump_cfg_string(oRemoteCommand, o->remote_command);
dump_cfg_string(oLogLevel, log_level_name(o->log_level));
dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
#ifdef ENABLE_PKCS11
dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
#endif
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
dump_cfg_string(oXAuthLocation, o->xauth_location);
/* Forwards */
dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
/* String array options */
dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
/* Special cases */
/* oConnectTimeout */
if (o->connection_timeout == -1)
printf("connecttimeout none\n");
else
dump_cfg_int(oConnectTimeout, o->connection_timeout);
/* oTunnelDevice */
printf("tunneldevice");
if (o->tun_local == SSH_TUNID_ANY)
printf(" any");
else
printf(" %d", o->tun_local);
if (o->tun_remote == SSH_TUNID_ANY)
printf(":any");
else
printf(":%d", o->tun_remote);
printf("\n");
/* oCanonicalizePermittedCNAMEs */
if ( o->num_permitted_cnames > 0) {
printf("canonicalizePermittedcnames");
for (i = 0; i < o->num_permitted_cnames; i++) {
printf(" %s:%s", o->permitted_cnames[i].source_list,
o->permitted_cnames[i].target_list);
}
printf("\n");
}
/* oControlPersist */
if (o->control_persist == 0 || o->control_persist_timeout == 0)
dump_cfg_fmtint(oControlPersist, o->control_persist);
else
dump_cfg_int(oControlPersist, o->control_persist_timeout);
/* oEscapeChar */
if (o->escape_char == SSH_ESCAPECHAR_NONE)
printf("escapechar none\n");
else {
vis(buf, o->escape_char, VIS_WHITE, 0);
printf("escapechar %s\n", buf);
}
/* oIPQoS */
printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
printf("%s\n", iptos2str(o->ip_qos_bulk));
/* oRekeyLimit */
printf("rekeylimit %llu %d\n",
(unsigned long long)o->rekey_limit, o->rekey_interval);
/* oStreamLocalBindMask */
printf("streamlocalbindmask 0%o\n",
o->fwd_opts.streamlocal_bind_mask);
/* oLogFacility */
printf("syslogfacility %s\n", log_facility_name(o->log_facility));
/* oProxyCommand / oProxyJump */
if (o->jump_host == NULL)
dump_cfg_string(oProxyCommand, o->proxy_command);
else {
/* Check for numeric addresses */
i = strchr(o->jump_host, ':') != NULL ||
strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
snprintf(buf, sizeof(buf), "%d", o->jump_port);
printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
/* optional additional jump spec */
o->jump_extra == NULL ? "" : o->jump_extra,
o->jump_extra == NULL ? "" : ",",
/* optional user */
o->jump_user == NULL ? "" : o->jump_user,
o->jump_user == NULL ? "" : "@",
/* opening [ if hostname is numeric */
i ? "[" : "",
/* mandatory hostname */
o->jump_host,
/* closing ] if hostname is numeric */
i ? "]" : "",
/* optional port number */
o->jump_port <= 0 ? "" : ":",
o->jump_port <= 0 ? "" : buf);
}
}
diff --git a/readconf.h b/readconf.h
index fc7e3825101d..8e36bf32adb3 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,219 +1,219 @@
-/* $OpenBSD: readconf.h,v 1.128 2018/09/20 03:30:44 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.129 2018/11/23 05:08:07 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Functions for reading the configuration file.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef READCONF_H
#define READCONF_H
/* Data structure for representing option data. */
#define SSH_MAX_HOSTS_FILES 32
#define MAX_CANON_DOMAINS 32
#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
struct allowed_cname {
char *source_list;
char *target_list;
};
typedef struct {
int forward_agent; /* Forward authentication agent. */
int forward_x11; /* Forward X11 display. */
int forward_x11_timeout; /* Expiration for Cookies */
int forward_x11_trusted; /* Trust Forward X11 display. */
int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
char *xauth_location; /* Location for xauth program */
struct ForwardOptions fwd_opts; /* forwarding options */
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
int hostbased_authentication; /* ssh2's rhosts_rsa */
int challenge_response_authentication;
/* Try S/Key or TIS, authentication. */
int gss_authentication; /* Try GSS authentication */
int gss_deleg_creds; /* Delegate GSS credentials */
int password_authentication; /* Try password
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
int compression; /* Compress packets in both directions. */
int tcp_keep_alive; /* Set SO_KEEPALIVE. */
int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for logging. */
int port; /* Port to connect. */
int address_family;
int connection_attempts; /* Max attempts (seconds) before
* giving up */
int connection_timeout; /* Max time (seconds) before
* aborting connection attempt */
int number_of_password_prompts; /* Max number of password
* prompts. */
char *ciphers; /* SSH2 ciphers in order of preference. */
char *macs; /* SSH2 macs in order of preference. */
char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
char *ca_sign_algorithms; /* Allowed CA signature algorithms */
char *hostname; /* Real host to connect. */
char *host_key_alias; /* hostname alias for .ssh/known_hosts */
char *proxy_command; /* Proxy command for connecting the host. */
char *user; /* User to log in as. */
int escape_char; /* Escape character; -2 = none */
u_int num_system_hostfiles; /* Paths for /etc/ssh/ssh_known_hosts */
char *system_hostfiles[SSH_MAX_HOSTS_FILES];
u_int num_user_hostfiles; /* Path for $HOME/.ssh/known_hosts */
char *user_hostfiles[SSH_MAX_HOSTS_FILES];
char *preferred_authentications;
char *bind_address; /* local socket address for connection to sshd */
char *bind_interface; /* local interface for bind address */
char *pkcs11_provider; /* PKCS#11 provider */
int verify_host_key_dns; /* Verify host key using DNS */
int num_identity_files; /* Number of files for RSA/DSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES];
int identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
int num_certificate_files; /* Number of extra certificates for ssh. */
char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
int add_keys_to_agent;
char *identity_agent; /* Optional path to ssh-agent socket */
/* Local TCP/IP forward requests. */
int num_local_forwards;
struct Forward *local_forwards;
/* Remote TCP/IP forward requests. */
int num_remote_forwards;
struct Forward *remote_forwards;
int clear_forwardings;
/* stdio forwarding (-W) host and port */
char *stdio_forward_host;
int stdio_forward_port;
int enable_ssh_keysign;
int64_t rekey_limit;
int rekey_interval;
int no_host_authentication_for_localhost;
int identities_only;
int server_alive_interval;
int server_alive_count_max;
int num_send_env;
char **send_env;
int num_setenv;
char **setenv;
char *control_path;
int control_master;
int control_persist; /* ControlPersist flag */
int control_persist_timeout; /* ControlPersist timeout (seconds) */
int hash_known_hosts;
int tun_open; /* tun(4) */
int tun_local; /* force tun device (optional) */
int tun_remote; /* force tun device (optional) */
char *local_command;
int permit_local_command;
char *remote_command;
int visual_host_key;
int request_tty;
int proxy_use_fdpass;
int num_canonical_domains;
char *canonical_domains[MAX_CANON_DOMAINS];
int canonicalize_hostname;
int canonicalize_max_dots;
int canonicalize_fallback_local;
int num_permitted_cnames;
struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS];
char *revoked_host_keys;
int fingerprint_hash;
int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */
char *hostbased_key_types;
char *pubkey_key_types;
char *jump_user;
char *jump_host;
int jump_port;
char *jump_extra;
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
#define SSH_CANONICALISE_NO 0
#define SSH_CANONICALISE_YES 1
#define SSH_CANONICALISE_ALWAYS 2
#define SSHCTL_MASTER_NO 0
#define SSHCTL_MASTER_YES 1
#define SSHCTL_MASTER_AUTO 2
#define SSHCTL_MASTER_ASK 3
#define SSHCTL_MASTER_AUTO_ASK 4
#define REQUEST_TTY_AUTO 0
#define REQUEST_TTY_NO 1
#define REQUEST_TTY_YES 2
#define REQUEST_TTY_FORCE 3
#define SSHCONF_CHECKPERM 1 /* check permissions on config file */
#define SSHCONF_USERCONF 2 /* user provided config file not system */
-#define SSHCONF_POSTCANON 4 /* After hostname canonicalisation */
+#define SSHCONF_FINAL 4 /* Final pass over config, after canon. */
#define SSHCONF_NEVERMATCH 8 /* Match/Host never matches; internal only */
#define SSH_UPDATE_HOSTKEYS_NO 0
#define SSH_UPDATE_HOSTKEYS_YES 1
#define SSH_UPDATE_HOSTKEYS_ASK 2
#define SSH_STRICT_HOSTKEY_OFF 0
#define SSH_STRICT_HOSTKEY_NEW 1
#define SSH_STRICT_HOSTKEY_YES 2
#define SSH_STRICT_HOSTKEY_ASK 3
void initialize_options(Options *);
void fill_default_options(Options *);
void fill_default_options_for_canonicalization(Options *);
int process_config_line(Options *, struct passwd *, const char *,
const char *, char *, const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *,
- const char *, Options *, int);
+ const char *, Options *, int, int *);
int parse_forward(struct Forward *, const char *, int, int);
int parse_jump(const char *, Options *, int);
int parse_ssh_uri(const char *, char **, char **, int *);
int default_ssh_port(void);
int option_clear_or_none(const char *);
void dump_client_config(Options *o, const char *host);
void add_local_forward(Options *, const struct Forward *);
void add_remote_forward(Options *, const struct Forward *);
void add_identity_file(Options *, const char *, const char *, int);
void add_certificate_file(Options *, const char *, int);
#endif /* READCONF_H */
diff --git a/readpass.c b/readpass.c
index f160f866b885..44014ef8af55 100644
--- a/readpass.c
+++ b/readpass.c
@@ -1,192 +1,199 @@
-/* $OpenBSD: readpass.c,v 1.52 2018/07/18 11:34:04 dtucker Exp $ */
+/* $OpenBSD: readpass.c,v 1.53 2019/01/19 04:15:56 tb Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "xmalloc.h"
#include "misc.h"
#include "pathnames.h"
#include "log.h"
#include "ssh.h"
#include "uidswap.h"
static char *
ssh_askpass(char *askpass, const char *msg)
{
pid_t pid, ret;
size_t len;
char *pass;
int p[2], status;
char buf[1024];
void (*osigchld)(int);
if (fflush(stdout) != 0)
error("ssh_askpass: fflush: %s", strerror(errno));
if (askpass == NULL)
fatal("internal error: askpass undefined");
if (pipe(p) < 0) {
error("ssh_askpass: pipe: %s", strerror(errno));
return NULL;
}
osigchld = signal(SIGCHLD, SIG_DFL);
if ((pid = fork()) < 0) {
error("ssh_askpass: fork: %s", strerror(errno));
signal(SIGCHLD, osigchld);
return NULL;
}
if (pid == 0) {
close(p[0]);
if (dup2(p[1], STDOUT_FILENO) < 0)
fatal("ssh_askpass: dup2: %s", strerror(errno));
execlp(askpass, askpass, msg, (char *)NULL);
fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
}
close(p[1]);
len = 0;
do {
ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len);
if (r == -1 && errno == EINTR)
continue;
if (r <= 0)
break;
len += r;
} while (sizeof(buf) - 1 - len > 0);
buf[len] = '\0';
close(p[0]);
while ((ret = waitpid(pid, &status, 0)) < 0)
if (errno != EINTR)
break;
signal(SIGCHLD, osigchld);
if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
explicit_bzero(buf, sizeof(buf));
return NULL;
}
buf[strcspn(buf, "\r\n")] = '\0';
pass = xstrdup(buf);
explicit_bzero(buf, sizeof(buf));
return pass;
}
/*
* Reads a passphrase from /dev/tty with echo turned off/on. Returns the
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
* RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no
* tty is available
*/
char *
read_passphrase(const char *prompt, int flags)
{
- char *askpass = NULL, *ret, buf[1024];
+ char cr = '\r', *askpass = NULL, *ret, buf[1024];
int rppflags, use_askpass = 0, ttyfd;
rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF;
if (flags & RP_USE_ASKPASS)
use_askpass = 1;
else if (flags & RP_ALLOW_STDIN) {
if (!isatty(STDIN_FILENO)) {
debug("read_passphrase: stdin is not a tty");
use_askpass = 1;
}
} else {
rppflags |= RPP_REQUIRE_TTY;
ttyfd = open(_PATH_TTY, O_RDWR);
- if (ttyfd >= 0)
+ if (ttyfd >= 0) {
+ /*
+ * If we're on a tty, ensure that show the prompt at
+ * the beginning of the line. This will hopefully
+ * clobber any password characters the user has
+ * optimistically typed before echo is disabled.
+ */
+ (void)write(ttyfd, &cr, 1);
close(ttyfd);
- else {
+ } else {
debug("read_passphrase: can't open %s: %s", _PATH_TTY,
strerror(errno));
use_askpass = 1;
}
}
if ((flags & RP_USE_ASKPASS) && getenv("DISPLAY") == NULL)
return (flags & RP_ALLOW_EOF) ? NULL : xstrdup("");
if (use_askpass && getenv("DISPLAY")) {
if (getenv(SSH_ASKPASS_ENV))
askpass = getenv(SSH_ASKPASS_ENV);
else
askpass = _PATH_SSH_ASKPASS_DEFAULT;
if ((ret = ssh_askpass(askpass, prompt)) == NULL)
if (!(flags & RP_ALLOW_EOF))
return xstrdup("");
return ret;
}
if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
if (flags & RP_ALLOW_EOF)
return NULL;
return xstrdup("");
}
ret = xstrdup(buf);
explicit_bzero(buf, sizeof(buf));
return ret;
}
int
ask_permission(const char *fmt, ...)
{
va_list args;
char *p, prompt[1024];
int allowed = 0;
va_start(args, fmt);
vsnprintf(prompt, sizeof(prompt), fmt, args);
va_end(args);
p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF);
if (p != NULL) {
/*
* Accept empty responses and responses consisting
* of the word "yes" as affirmative.
*/
if (*p == '\0' || *p == '\n' ||
strcasecmp(p, "yes") == 0)
allowed = 1;
free(p);
}
return (allowed);
}
diff --git a/regress/Makefile b/regress/Makefile
index 647b4a049be3..925edf71a00d 100644
--- a/regress/Makefile
+++ b/regress/Makefile
@@ -1,241 +1,246 @@
-# $OpenBSD: Makefile,v 1.97 2018/06/07 04:46:34 djm Exp $
+# $OpenBSD: Makefile,v 1.100 2019/01/20 23:24:19 djm Exp $
REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec
tests: prep $(REGRESS_TARGETS)
# Interop tests are not run by default
interop interop-tests: t-exec-interop
prep:
test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out
clean:
for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done
- test -z "${SUDO}" || ${SUDO} rm -f ${SUDO_CLEAN}
rm -rf $(OBJ).putty
distclean: clean
LTESTS= connect \
proxy-connect \
connect-privsep \
connect-uri \
proto-version \
proto-mismatch \
exit-status \
envpass \
transfer \
banner \
rekey \
stderr-data \
stderr-after-eof \
broken-pipe \
try-ciphers \
yes-head \
login-timeout \
agent \
agent-getpeereid \
agent-timeout \
agent-ptrace \
keyscan \
keygen-change \
keygen-convert \
keygen-moduli \
key-options \
scp \
scp-uri \
sftp \
sftp-chroot \
sftp-cmds \
sftp-badcmds \
sftp-batch \
sftp-glob \
sftp-perm \
sftp-uri \
reconfigure \
dynamic-forward \
forwarding \
multiplex \
reexec \
brokenkeys \
sshcfgparse \
cfgparse \
cfgmatch \
cfgmatchlisten \
addrmatch \
localcommand \
forcecommand \
portnum \
keytype \
kextype \
cert-hostkey \
cert-userkey \
host-expand \
keys-command \
forward-control \
integrity \
krl \
multipubkey \
limit-keytype \
hostkey-agent \
keygen-knownhosts \
hostkey-rotate \
principals-command \
cert-file \
cfginclude \
allow-deny-users \
authinfo
# dhgex \
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
#INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp
-#LTESTS= cipher-speed
+EXTRA_TESTS= agent-pkcs11
+#EXTRA_TESTS+= cipher-speed
USERNAME= ${LOGNAME}
CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \
authorized_keys_${USERNAME}.* \
authorized_principals_${USERNAME} \
banner.in banner.out cert_host_key* cert_user_key* \
copy.1 copy.2 data ed25519-agent ed25519-agent* \
ed25519-agent.pub ed25519 ed25519.pub empty.in \
expect failed-regress.log failed-ssh.log failed-sshd.log \
hkr.* host.ed25519 host.rsa host.rsa1 host_* \
host_ca_key* host_krl_* host_revoked_* key.* \
key.dsa-* key.ecdsa-* key.ed25519-512 \
key.ed25519-512.pub key.rsa-* keys-command-args kh.* \
known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \
modpipe netcat no_identity_config \
pidfile putty.rsa2 ready regress.log \
remote_pid revoked-* rsa rsa-agent rsa-agent.pub rsa.pub \
rsa1 rsa1-agent rsa1-agent.pub rsa1.pub rsa_ssh2_cr.prv \
rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \
scp-ssh-wrapper.scp setuid-allowed sftp-server.log \
sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \
ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \
ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \
sshd_config.orig sshd_proxy sshd_proxy.* sshd_proxy_bak \
sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \
t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \
t8.out t8.out.pub t9.out t9.out.pub testdata \
user_*key* user_ca* user_key*
-SUDO_CLEAN+= /var/run/testdata_${USERNAME} /var/run/keycommand_${USERNAME}
-
# Enable all malloc(3) randomisations and checks
TEST_ENV= "MALLOC_OPTIONS=CFGJRSUX"
TEST_SSH_SSHKEYGEN?=ssh-keygen
CPPFLAGS=-I..
t1:
${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv
tr '\n' '\r' <${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_cr.prv
${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_cr.prv | diff - ${.CURDIR}/rsa_openssh.prv
awk '{print $$0 "\r"}' ${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_crnl.prv
${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_crnl.prv | diff - ${.CURDIR}/rsa_openssh.prv
t2:
cat ${.CURDIR}/rsa_openssh.prv > $(OBJ)/t2.out
chmod 600 $(OBJ)/t2.out
${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub
t3:
${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out
${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub
t4:
${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\
awk '{print $$2}' | diff - ${.CURDIR}/t4.ok
t5:
${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\
awk '{print $$2}' | diff - ${.CURDIR}/t5.ok
t6:
${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1
${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2
chmod 600 $(OBJ)/t6.out1
${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t6.out1 | diff - $(OBJ)/t6.out2
$(OBJ)/t7.out:
${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@
t7: $(OBJ)/t7.out
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null
$(OBJ)/t8.out:
${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@
t8: $(OBJ)/t8.out
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null
$(OBJ)/t9.out:
test "${TEST_SSH_ECC}" != yes || \
${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@
t9: $(OBJ)/t9.out
test "${TEST_SSH_ECC}" != yes || \
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t9.out > /dev/null
test "${TEST_SSH_ECC}" != yes || \
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null
$(OBJ)/t10.out:
${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -f $@
t10: $(OBJ)/t10.out
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null
t11:
${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\
awk '{print $$2}' | diff - ${.CURDIR}/t11.ok
$(OBJ)/t12.out:
${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@
t12: $(OBJ)/t12.out
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null
t-exec: ${LTESTS:=.sh}
@if [ "x$?" = "x" ]; then exit 0; fi; \
for TEST in ""$?; do \
echo "run test $${TEST}" ... 1>&2; \
(env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
done
t-exec-interop: ${INTEROP_TESTS:=.sh}
@if [ "x$?" = "x" ]; then exit 0; fi; \
for TEST in ""$?; do \
echo "run test $${TEST}" ... 1>&2; \
(env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
done
+t-extra: ${EXTRA_TESTS:=.sh}
+ @if [ "x$?" = "x" ]; then exit 0; fi; \
+ for TEST in ""$?; do \
+ echo "run test $${TEST}" ... 1>&2; \
+ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \
+ done
+
# Not run by default
interop: ${INTEROP_TARGETS}
# Unit tests, built by top-level Makefile
unit:
set -e ; if test -z "${SKIP_UNIT}" ; then \
V="" ; \
test "x${USE_VALGRIND}" = "x" || \
V=${.CURDIR}/valgrind-unit.sh ; \
$$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
$$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
-d ${.CURDIR}/unittests/sshkey/testdata ; \
$$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \
$$V ${.OBJDIR}/unittests/conversion/test_conversion ; \
$$V ${.OBJDIR}/unittests/kex/test_kex ; \
$$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \
-d ${.CURDIR}/unittests/hostkeys/testdata ; \
$$V ${.OBJDIR}/unittests/match/test_match ; \
if test "x${TEST_SSH_UTF8}" = "xyes" ; then \
$$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \
fi \
fi
diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh
index db3018b885fe..5205d906712c 100755
--- a/regress/agent-pkcs11.sh
+++ b/regress/agent-pkcs11.sh
@@ -1,71 +1,124 @@
-# $OpenBSD: agent-pkcs11.sh,v 1.3 2017/04/30 23:34:55 djm Exp $
+# $OpenBSD: agent-pkcs11.sh,v 1.6 2019/01/21 09:13:41 djm Exp $
# Placed in the Public Domain.
tid="pkcs11 agent test"
-TEST_SSH_PIN=""
-TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0
+try_token_libs() {
+ for _lib in "$@" ; do
+ if test -f "$_lib" ; then
+ verbose "Using token library $_lib"
+ TEST_SSH_PKCS11="$_lib"
+ return
+ fi
+ done
+ echo "skipped: Unable to find PKCS#11 token library"
+ exit 0
+}
+
+try_token_libs \
+ /usr/local/lib/softhsm/libsofthsm2.so \
+ /usr/lib64/pkcs11/libsofthsm2.so \
+ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so
+
+TEST_SSH_PIN=1234
+TEST_SSH_SOPIN=12345678
+if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then
+ SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}"
+ export SSH_PKCS11_HELPER
+fi
test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"
-# setup environment for soft-pkcs11 token
-SOFTPKCS11RC=$OBJ/pkcs11.info
-export SOFTPKCS11RC
+# setup environment for softhsm2 token
+DIR=$OBJ/SOFTHSM
+rm -rf $DIR
+TOKEN=$DIR/tokendir
+mkdir -p $TOKEN
+SOFTHSM2_CONF=$DIR/softhsm2.conf
+export SOFTHSM2_CONF
+cat > $SOFTHSM2_CONF << EOF
+# SoftHSM v2 configuration file
+directories.tokendir = ${TOKEN}
+objectstore.backend = file
+# ERROR, WARNING, INFO, DEBUG
+log.level = DEBUG
+# If CKF_REMOVABLE_DEVICE flag should be set
+slots.removable = false
+EOF
+out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN")
+slot=$(echo -- $out | sed 's/.* //')
+
# prevent ssh-agent from calling ssh-askpass
SSH_ASKPASS=/usr/bin/true
export SSH_ASKPASS
unset DISPLAY
# start command w/o tty, so ssh-add accepts pin from stdin
notty() {
perl -e 'use POSIX; POSIX::setsid();
if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@"
}
+trace "generating keys"
+RSA=${DIR}/RSA
+EC=${DIR}/EC
+openssl genpkey -algorithm rsa > $RSA
+openssl pkcs8 -nocrypt -in $RSA |\
+ softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" --import /dev/stdin
+openssl genpkey \
+ -genparam \
+ -algorithm ec \
+ -pkeyopt ec_paramgen_curve:prime256v1 |\
+ openssl genpkey \
+ -paramfile /dev/stdin > $EC
+openssl pkcs8 -nocrypt -in $EC |\
+ softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" --import /dev/stdin
+
trace "start agent"
eval `${SSHAGENT} -s` > /dev/null
r=$?
if [ $r -ne 0 ]; then
fail "could not start ssh-agent: exit code $r"
else
- trace "generating key/cert"
- rm -f $OBJ/pkcs11.key $OBJ/pkcs11.crt
- openssl genrsa -out $OBJ/pkcs11.key 2048 > /dev/null 2>&1
- chmod 600 $OBJ/pkcs11.key
- openssl req -key $OBJ/pkcs11.key -new -x509 \
- -out $OBJ/pkcs11.crt -text -subj '/CN=pkcs11 test' > /dev/null
- printf "a\ta\t$OBJ/pkcs11.crt\t$OBJ/pkcs11.key" > $SOFTPKCS11RC
- # add to authorized keys
- ${SSHKEYGEN} -y -f $OBJ/pkcs11.key > $OBJ/authorized_keys_$USER
-
trace "add pkcs11 key to agent"
echo ${TEST_SSH_PIN} | notty ${SSHADD} -s ${TEST_SSH_PKCS11} > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -s failed: exit code $r"
fi
trace "pkcs11 list via agent"
${SSHADD} -l > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -l failed: exit code $r"
fi
- trace "pkcs11 connect via agent"
- ${SSH} -F $OBJ/ssh_proxy somehost exit 5
- r=$?
- if [ $r -ne 5 ]; then
- fail "ssh connect failed (exit code $r)"
- fi
+ for k in $RSA $EC; do
+ trace "testing $k"
+ chmod 600 $k
+ ssh-keygen -y -f $k > $k.pub
+ pub=$(cat $k.pub)
+ ${SSHADD} -L | grep -q "$pub" || fail "key $k missing in ssh-add -L"
+ ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed"
+
+ # add to authorized keys
+ cat $k.pub > $OBJ/authorized_keys_$USER
+ trace "pkcs11 connect via agent ($k)"
+ ${SSH} -F $OBJ/ssh_proxy somehost exit 5
+ r=$?
+ if [ $r -ne 5 ]; then
+ fail "ssh connect failed (exit code $r)"
+ fi
+ done
trace "remove pkcs11 keys"
echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -e failed: exit code $r"
fi
trace "kill agent"
${SSHAGENT} -k > /dev/null
fi
diff --git a/regress/agent-timeout.sh b/regress/agent-timeout.sh
index 9598c2032d26..80012f80c7c1 100644
--- a/regress/agent-timeout.sh
+++ b/regress/agent-timeout.sh
@@ -1,36 +1,38 @@
-# $OpenBSD: agent-timeout.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
+# $OpenBSD: agent-timeout.sh,v 1.4 2019/01/28 00:08:26 dtucker Exp $
# Placed in the Public Domain.
tid="agent timeout test"
SSHAGENT_TIMEOUT=10
trace "start agent"
eval `${SSHAGENT} -s` > /dev/null
r=$?
if [ $r -ne 0 ]; then
fail "could not start ssh-agent: exit code $r"
else
trace "add keys with timeout"
+ keys=0
for t in ${SSH_KEYTYPES}; do
${SSHADD} -t ${SSHAGENT_TIMEOUT} $OBJ/$t > /dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh-add did succeed exit code 0"
fi
+ keys=$((${keys} + 1))
done
n=`${SSHADD} -l 2> /dev/null | wc -l`
trace "agent has $n keys"
- if [ $n -ne 2 ]; then
- fail "ssh-add -l did not return 2 keys: $n"
+ if [ $n -ne $keys ]; then
+ fail "ssh-add -l did not return $keys keys: $n"
fi
trace "sleeping 2*${SSHAGENT_TIMEOUT} seconds"
sleep ${SSHAGENT_TIMEOUT}
sleep ${SSHAGENT_TIMEOUT}
${SSHADD} -l 2> /dev/null | grep 'The agent has no identities.' >/dev/null
if [ $? -ne 0 ]; then
fail "ssh-add -l still returns keys after timeout"
fi
trace "kill agent"
${SSHAGENT} -k > /dev/null
fi
diff --git a/regress/agent.sh b/regress/agent.sh
index 7111056c9be4..788b02064715 100644
--- a/regress/agent.sh
+++ b/regress/agent.sh
@@ -1,117 +1,122 @@
-# $OpenBSD: agent.sh,v 1.13 2017/12/19 00:49:30 djm Exp $
+# $OpenBSD: agent.sh,v 1.14 2019/01/28 00:12:36 dtucker Exp $
# Placed in the Public Domain.
tid="simple agent test"
SSH_AUTH_SOCK=/nonexistent ${SSHADD} -l > /dev/null 2>&1
if [ $? -ne 2 ]; then
fail "ssh-add -l did not fail with exit code 2"
fi
trace "start agent"
eval `${SSHAGENT} -s` > /dev/null
r=$?
if [ $r -ne 0 ]; then
fatal "could not start ssh-agent: exit code $r"
fi
${SSHADD} -l > /dev/null 2>&1
if [ $? -ne 1 ]; then
fail "ssh-add -l did not fail with exit code 1"
fi
rm -f $OBJ/user_ca_key $OBJ/user_ca_key.pub
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key \
|| fatal "ssh-keygen failed"
trace "overwrite authorized keys"
printf '' > $OBJ/authorized_keys_$USER
+echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/ssh_proxy
+echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/sshd_proxy
+
for t in ${SSH_KEYTYPES}; do
# generate user key for agent
rm -f $OBJ/$t-agent $OBJ/$t-agent.pub*
${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\
fatal "ssh-keygen for $t-agent failed"
# Make a certificate for each too.
${SSHKEYGEN} -qs $OBJ/user_ca_key -I "$t cert" \
-n estragon $OBJ/$t-agent.pub || fatal "ca sign failed"
# add to authorized keys
cat $OBJ/$t-agent.pub >> $OBJ/authorized_keys_$USER
# add privat key to agent
${SSHADD} $OBJ/$t-agent > /dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh-add did succeed exit code 0"
fi
# Remove private key to ensure that we aren't accidentally using it.
rm -f $OBJ/$t-agent
done
# Remove explicit identity directives from ssh_proxy
mv $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
grep -vi identityfile $OBJ/ssh_proxy_bak > $OBJ/ssh_proxy
${SSHADD} -l > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -l failed: exit code $r"
fi
# the same for full pubkey output
${SSHADD} -L > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -L failed: exit code $r"
fi
trace "simple connect via agent"
${SSH} -F $OBJ/ssh_proxy somehost exit 52
r=$?
if [ $r -ne 52 ]; then
fail "ssh connect with failed (exit code $r)"
fi
for t in ${SSH_KEYTYPES}; do
trace "connect via agent using $t key"
${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \
somehost exit 52
r=$?
if [ $r -ne 52 ]; then
fail "ssh connect with failed (exit code $r)"
fi
done
trace "agent forwarding"
${SSH} -A -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -l via agent fwd failed (exit code $r)"
fi
${SSH} -A -F $OBJ/ssh_proxy somehost \
"${SSH} -F $OBJ/ssh_proxy somehost exit 52"
r=$?
if [ $r -ne 52 ]; then
fail "agent fwd failed (exit code $r)"
fi
(printf 'cert-authority,principals="estragon" '; cat $OBJ/user_ca_key.pub) \
> $OBJ/authorized_keys_$USER
for t in ${SSH_KEYTYPES}; do
+ if [ "$t" != "ssh-dss" ]; then
trace "connect via agent using $t key"
${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub \
-oCertificateFile=$OBJ/$t-agent-cert.pub \
-oIdentitiesOnly=yes somehost exit 52
r=$?
if [ $r -ne 52 ]; then
fail "ssh connect with failed (exit code $r)"
fi
+ fi
done
trace "delete all agent keys"
${SSHADD} -D > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -D failed: exit code $r"
fi
trace "kill agent"
${SSHAGENT} -k > /dev/null
diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh
index d2ecd318beae..3ce777967a5d 100755
--- a/regress/cert-hostkey.sh
+++ b/regress/cert-hostkey.sh
@@ -1,321 +1,321 @@
-# $OpenBSD: cert-hostkey.sh,v 1.16 2018/07/03 11:43:49 djm Exp $
+# $OpenBSD: cert-hostkey.sh,v 1.17 2018/10/31 11:09:27 dtucker Exp $
# Placed in the Public Domain.
tid="certified host keys"
rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/host_revoked_*
rm -f $OBJ/cert_host_key* $OBJ/host_krl_*
# Allow all hostkey/pubkey types, prefer certs for the client
types=""
for i in `$SSH -Q key`; do
if [ -z "$types" ]; then
types="$i"
continue
fi
case "$i" in
# Special treatment for RSA keys.
*rsa*cert*)
types="rsa-sha2-256-cert-v01@openssh.com,$i,$types"
types="rsa-sha2-512-cert-v01@openssh.com,$types";;
*rsa*)
types="$types,rsa-sha2-512,rsa-sha2-256,$i";;
# Prefer certificate to plain keys.
*cert*) types="$i,$types";;
*) types="$types,$i";;
esac
done
(
echo "HostKeyAlgorithms ${types}"
echo "PubkeyAcceptedKeyTypes *"
) >> $OBJ/ssh_proxy
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
(
echo "HostKeyAlgorithms *"
echo "PubkeyAcceptedKeyTypes *"
) >> $OBJ/sshd_proxy_bak
HOSTS='localhost-with-alias,127.0.0.1,::1'
kh_ca() {
for k in "$@" ; do
printf "@cert-authority $HOSTS "
cat $OBJ/$k || fatal "couldn't cat $k"
done
}
kh_revoke() {
for k in "$@" ; do
printf "@revoked * "
cat $OBJ/$k || fatal "couldn't cat $k"
done
}
# Create a CA key and add it to known hosts. Ed25519 chosen for speed.
# RSA for testing RSA/SHA2 signatures.
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/host_ca_key ||\
fail "ssh-keygen of host_ca_key failed"
${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/host_ca_key2 ||\
fail "ssh-keygen of host_ca_key failed"
kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
# Plain text revocation files
touch $OBJ/host_revoked_empty
touch $OBJ/host_revoked_plain
touch $OBJ/host_revoked_cert
cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
fi
# Prepare certificate, plain key and CA KRLs
${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed"
${SSHKEYGEN} -kf $OBJ/host_krl_plain || fatal "KRL init failed"
${SSHKEYGEN} -kf $OBJ/host_krl_cert || fatal "KRL init failed"
${SSHKEYGEN} -kf $OBJ/host_krl_ca $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub \
|| fatal "KRL init failed"
# Generate and sign host keys
serial=1
for ktype in $PLAIN_TYPES ; do
verbose "$tid: sign host ${ktype} cert"
# Generate and sign a host key
${SSHKEYGEN} -q -N '' -t ${ktype} \
-f $OBJ/cert_host_key_${ktype} || \
fatal "ssh-keygen of cert_host_key_${ktype} failed"
${SSHKEYGEN} -ukf $OBJ/host_krl_plain \
$OBJ/cert_host_key_${ktype}.pub || fatal "KRL update failed"
cat $OBJ/cert_host_key_${ktype}.pub >> $OBJ/host_revoked_plain
case $ktype in
rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;;
*) tflag=""; ca="$OBJ/host_ca_key" ;;
esac
${SSHKEYGEN} -h -q -s $ca -z $serial $tflag \
-I "regress host key for $USER" \
-n $HOSTS $OBJ/cert_host_key_${ktype} ||
fatal "couldn't sign cert_host_key_${ktype}"
${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
$OBJ/cert_host_key_${ktype}-cert.pub || \
fatal "KRL update failed"
cat $OBJ/cert_host_key_${ktype}-cert.pub >> $OBJ/host_revoked_cert
serial=`expr $serial + 1`
done
attempt_connect() {
_ident="$1"
_expect_success="$2"
shift; shift
verbose "$tid: $_ident expect success $_expect_success"
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
"$@" -F $OBJ/ssh_proxy somehost true
_r=$?
if [ "x$_expect_success" = "xyes" ] ; then
if [ $_r -ne 0 ]; then
fail "ssh cert connect $_ident failed"
fi
else
if [ $_r -eq 0 ]; then
fail "ssh cert connect $_ident succeeded unexpectedly"
fi
fi
}
# Basic connect and revocation tests.
-for privsep in yes no ; do
+for privsep in yes sandbox ; do
for ktype in $PLAIN_TYPES ; do
verbose "$tid: host ${ktype} cert connect privsep $privsep"
(
cat $OBJ/sshd_proxy_bak
echo HostKey $OBJ/cert_host_key_${ktype}
echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
echo UsePrivilegeSeparation $privsep
) > $OBJ/sshd_proxy
# test name expect success
attempt_connect "$ktype basic connect" "yes"
attempt_connect "$ktype empty KRL" "yes" \
-oRevokedHostKeys=$OBJ/host_krl_empty
attempt_connect "$ktype KRL w/ plain key revoked" "no" \
-oRevokedHostKeys=$OBJ/host_krl_plain
attempt_connect "$ktype KRL w/ cert revoked" "no" \
-oRevokedHostKeys=$OBJ/host_krl_cert
attempt_connect "$ktype KRL w/ CA revoked" "no" \
-oRevokedHostKeys=$OBJ/host_krl_ca
attempt_connect "$ktype empty plaintext revocation" "yes" \
-oRevokedHostKeys=$OBJ/host_revoked_empty
attempt_connect "$ktype plain key plaintext revocation" "no" \
-oRevokedHostKeys=$OBJ/host_revoked_plain
attempt_connect "$ktype cert plaintext revocation" "no" \
-oRevokedHostKeys=$OBJ/host_revoked_cert
attempt_connect "$ktype CA plaintext revocation" "no" \
-oRevokedHostKeys=$OBJ/host_revoked_ca
done
done
# Revoked certificates with key present
kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
for ktype in $PLAIN_TYPES ; do
test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey"
kh_revoke cert_host_key_${ktype}.pub >> $OBJ/known_hosts-cert.orig
done
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
-for privsep in yes no ; do
+for privsep in yes sandbox ; do
for ktype in $PLAIN_TYPES ; do
verbose "$tid: host ${ktype} revoked cert privsep $privsep"
(
cat $OBJ/sshd_proxy_bak
echo HostKey $OBJ/cert_host_key_${ktype}
echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
echo UsePrivilegeSeparation $privsep
) > $OBJ/sshd_proxy
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
done
done
# Revoked CA
kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
kh_revoke host_ca_key.pub host_ca_key2.pub >> $OBJ/known_hosts-cert.orig
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
for ktype in $PLAIN_TYPES ; do
verbose "$tid: host ${ktype} revoked cert"
(
cat $OBJ/sshd_proxy_bak
echo HostKey $OBJ/cert_host_key_${ktype}
echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
) > $OBJ/sshd_proxy
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
done
# Create a CA key and add it to known hosts
kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
test_one() {
ident=$1
result=$2
sign_opts=$3
for kt in rsa ed25519 ; do
case $ktype in
rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;;
*) tflag=""; ca="$OBJ/host_ca_key" ;;
esac
${SSHKEYGEN} -q -s $ca $tflag -I "regress host key for $USER" \
$sign_opts $OBJ/cert_host_key_${kt} ||
fatal "couldn't sign cert_host_key_${kt}"
(
cat $OBJ/sshd_proxy_bak
echo HostKey $OBJ/cert_host_key_${kt}
echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
) > $OBJ/sshd_proxy
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
rc=$?
if [ "x$result" = "xsuccess" ] ; then
if [ $rc -ne 0 ]; then
fail "ssh cert connect $ident failed unexpectedly"
fi
else
if [ $rc -eq 0 ]; then
fail "ssh cert connect $ident succeeded unexpectedly"
fi
fi
done
}
test_one "user-certificate" failure "-n $HOSTS"
test_one "empty principals" success "-h"
test_one "wrong principals" failure "-h -n foo"
test_one "cert not yet valid" failure "-h -V20200101:20300101"
test_one "cert expired" failure "-h -V19800101:19900101"
test_one "cert valid interval" success "-h -V-1w:+2w"
test_one "cert has constraints" failure "-h -Oforce-command=false"
# Check downgrade of cert to raw key when no CA found
for ktype in $PLAIN_TYPES ; do
rm -f $OBJ/known_hosts-cert $OBJ/cert_host_key*
verbose "$tid: host ${ktype} ${v} cert downgrade to raw key"
# Generate and sign a host key
${SSHKEYGEN} -q -N '' -t ${ktype} -f $OBJ/cert_host_key_${ktype} || \
fail "ssh-keygen of cert_host_key_${ktype} failed"
case $ktype in
rsa-sha2-*) tflag="-t $ktype"; ca="$OBJ/host_ca_key2" ;;
*) tflag=""; ca="$OBJ/host_ca_key" ;;
esac
${SSHKEYGEN} -h -q $tflag -s $ca $tflag \
-I "regress host key for $USER" \
-n $HOSTS $OBJ/cert_host_key_${ktype} ||
fatal "couldn't sign cert_host_key_${ktype}"
(
printf "$HOSTS "
cat $OBJ/cert_host_key_${ktype}.pub
) > $OBJ/known_hosts-cert
(
cat $OBJ/sshd_proxy_bak
echo HostKey $OBJ/cert_host_key_${ktype}
echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
) > $OBJ/sshd_proxy
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
done
# Wrong certificate
kh_ca host_ca_key.pub host_ca_key2.pub > $OBJ/known_hosts-cert.orig
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
for kt in $PLAIN_TYPES ; do
verbose "$tid: host ${kt} connect wrong cert"
rm -f $OBJ/cert_host_key*
# Self-sign key
${SSHKEYGEN} -q -N '' -t ${kt} -f $OBJ/cert_host_key_${kt} || \
fail "ssh-keygen of cert_host_key_${kt} failed"
case $kt in
rsa-sha2-*) tflag="-t $kt" ;;
*) tflag="" ;;
esac
${SSHKEYGEN} $tflag -h -q -s $OBJ/cert_host_key_${kt} \
-I "regress host key for $USER" \
-n $HOSTS $OBJ/cert_host_key_${kt} ||
fatal "couldn't sign cert_host_key_${kt}"
(
cat $OBJ/sshd_proxy_bak
echo HostKey $OBJ/cert_host_key_${kt}
echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
) > $OBJ/sshd_proxy
cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect $ident succeeded unexpectedly"
fi
done
rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/cert_host_key*
diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh
index 30c2c156d2f1..6849e9922649 100755
--- a/regress/cert-userkey.sh
+++ b/regress/cert-userkey.sh
@@ -1,391 +1,391 @@
-# $OpenBSD: cert-userkey.sh,v 1.19 2018/03/12 00:54:04 djm Exp $
+# $OpenBSD: cert-userkey.sh,v 1.20 2018/10/31 11:09:27 dtucker Exp $
# Placed in the Public Domain.
tid="certified user keys"
rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
EXTRA_TYPES=""
if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
fi
kname() {
case $ktype in
rsa-sha2-*) n="$ktype" ;;
# subshell because some seds will add a newline
*) n=$(echo $1 | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;;
esac
echo "$n*,ssh-rsa*,ssh-ed25519*"
}
# Create a CA key
${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_ca_key ||\
fail "ssh-keygen of user_ca_key failed"
# Generate and sign user keys
for ktype in $PLAIN_TYPES $EXTRA_TYPES ; do
verbose "$tid: sign user ${ktype} cert"
${SSHKEYGEN} -q -N '' -t ${ktype} \
-f $OBJ/cert_user_key_${ktype} || \
fatal "ssh-keygen of cert_user_key_${ktype} failed"
# Generate RSA/SHA2 certs for rsa-sha2* keys.
case $ktype in
rsa-sha2-*) tflag="-t $ktype" ;;
*) tflag="" ;;
esac
${SSHKEYGEN} -q -s $OBJ/user_ca_key -z $$ \
-I "regress user key for $USER" \
-n ${USER},mekmitasdigoat $tflag $OBJ/cert_user_key_${ktype} || \
fatal "couldn't sign cert_user_key_${ktype}"
done
# Test explicitly-specified principals
for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
t=$(kname $ktype)
- for privsep in yes no ; do
+ for privsep in yes sandbox ; do
_prefix="${ktype} privsep $privsep"
# Setup for AuthorizedPrincipalsFile
rm -f $OBJ/authorized_keys_$USER
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
echo "AuthorizedPrincipalsFile " \
"$OBJ/authorized_principals_%u"
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
echo "PubkeyAcceptedKeyTypes ${t}"
) > $OBJ/sshd_proxy
(
cat $OBJ/ssh_proxy_bak
echo "PubkeyAcceptedKeyTypes ${t}"
) > $OBJ/ssh_proxy
# Missing authorized_principals
verbose "$tid: ${_prefix} missing authorized_principals"
rm -f $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Empty authorized_principals
verbose "$tid: ${_prefix} empty authorized_principals"
echo > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Wrong authorized_principals
verbose "$tid: ${_prefix} wrong authorized_principals"
echo gregorsamsa > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Correct authorized_principals
verbose "$tid: ${_prefix} correct authorized_principals"
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
# authorized_principals with bad key option
verbose "$tid: ${_prefix} authorized_principals bad key opt"
echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# authorized_principals with command=false
verbose "$tid: ${_prefix} authorized_principals command=false"
echo 'command="false" mekmitasdigoat' > \
$OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# authorized_principals with command=true
verbose "$tid: ${_prefix} authorized_principals command=true"
echo 'command="true" mekmitasdigoat' > \
$OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
# Setup for principals= key option
rm -f $OBJ/authorized_principals_$USER
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
echo "PubkeyAcceptedKeyTypes ${t}"
) > $OBJ/sshd_proxy
(
cat $OBJ/ssh_proxy_bak
echo "PubkeyAcceptedKeyTypes ${t}"
) > $OBJ/ssh_proxy
# Wrong principals list
verbose "$tid: ${_prefix} wrong principals key option"
(
printf 'cert-authority,principals="gregorsamsa" '
cat $OBJ/user_ca_key.pub
) > $OBJ/authorized_keys_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Correct principals list
verbose "$tid: ${_prefix} correct principals key option"
(
printf 'cert-authority,principals="mekmitasdigoat" '
cat $OBJ/user_ca_key.pub
) > $OBJ/authorized_keys_$USER
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
done
done
basic_tests() {
auth=$1
if test "x$auth" = "xauthorized_keys" ; then
# Add CA to authorized_keys
(
printf 'cert-authority '
cat $OBJ/user_ca_key.pub
) > $OBJ/authorized_keys_$USER
else
echo > $OBJ/authorized_keys_$USER
extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
fi
for ktype in $PLAIN_TYPES ; do
t=$(kname $ktype)
for privsep in yes no ; do
_prefix="${ktype} privsep $privsep $auth"
# Simple connect
verbose "$tid: ${_prefix} connect"
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
echo "PubkeyAcceptedKeyTypes ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
(
cat $OBJ/ssh_proxy_bak
echo "PubkeyAcceptedKeyTypes ${t}"
) > $OBJ/ssh_proxy
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
# Revoked keys
verbose "$tid: ${_prefix} revoked key"
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
echo "RevokedKeys $OBJ/cert_user_key_revoked"
echo "PubkeyAcceptedKeyTypes ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
cp $OBJ/cert_user_key_${ktype}.pub \
$OBJ/cert_user_key_revoked
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpecedly"
fi
verbose "$tid: ${_prefix} revoked via KRL"
rm $OBJ/cert_user_key_revoked
${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
$OBJ/cert_user_key_${ktype}.pub
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpecedly"
fi
verbose "$tid: ${_prefix} empty KRL"
${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
done
# Revoked CA
verbose "$tid: ${ktype} $auth revoked CA key"
(
cat $OBJ/sshd_proxy_bak
echo "RevokedKeys $OBJ/user_ca_key.pub"
echo "PubkeyAcceptedKeyTypes ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpecedly"
fi
done
verbose "$tid: $auth CA does not authenticate"
(
cat $OBJ/sshd_proxy_bak
echo "PubkeyAcceptedKeyTypes ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
verbose "$tid: ensure CA key does not authenticate user"
${SSH} -i $OBJ/user_ca_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect with CA key succeeded unexpectedly"
fi
}
basic_tests authorized_keys
basic_tests TrustedUserCAKeys
test_one() {
ident=$1
result=$2
sign_opts=$3
auth_choice=$4
auth_opt=$5
if test "x$auth_choice" = "x" ; then
auth_choice="authorized_keys TrustedUserCAKeys"
fi
for auth in $auth_choice ; do
for ktype in rsa ed25519 ; do
cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
if test "x$auth" = "xauthorized_keys" ; then
# Add CA to authorized_keys
(
printf "cert-authority${auth_opt} "
cat $OBJ/user_ca_key.pub
) > $OBJ/authorized_keys_$USER
else
echo > $OBJ/authorized_keys_$USER
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
>> $OBJ/sshd_proxy
echo "PubkeyAcceptedKeyTypes ${t}*" \
>> $OBJ/sshd_proxy
if test "x$auth_opt" != "x" ; then
echo $auth_opt >> $OBJ/sshd_proxy
fi
fi
verbose "$tid: $ident auth $auth expect $result $ktype"
${SSHKEYGEN} -q -s $OBJ/user_ca_key \
-I "regress user key for $USER" \
$sign_opts $OBJ/cert_user_key_${ktype} ||
fail "couldn't sign cert_user_key_${ktype}"
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
rc=$?
if [ "x$result" = "xsuccess" ] ; then
if [ $rc -ne 0 ]; then
fail "$ident failed unexpectedly"
fi
else
if [ $rc -eq 0 ]; then
fail "$ident succeeded unexpectedly"
fi
fi
done
done
}
test_one "correct principal" success "-n ${USER}"
test_one "host-certificate" failure "-n ${USER} -h"
test_one "wrong principals" failure "-n foo"
test_one "cert not yet valid" failure "-n ${USER} -V20200101:20300101"
test_one "cert expired" failure "-n ${USER} -V19800101:19900101"
test_one "cert valid interval" success "-n ${USER} -V-1w:+2w"
test_one "wrong source-address" failure "-n ${USER} -Osource-address=10.0.0.0/8"
test_one "force-command" failure "-n ${USER} -Oforce-command=false"
# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
test_one "empty principals" success "" authorized_keys
test_one "empty principals" failure "" TrustedUserCAKeys
# Check explicitly-specified principals: an empty principals list in the cert
# should always be refused.
# AuthorizedPrincipalsFile
rm -f $OBJ/authorized_keys_$USER
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
test_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
test_one "AuthorizedPrincipalsFile no principals" failure "" \
TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
# principals= key option
rm -f $OBJ/authorized_principals_$USER
test_one "principals key option principals" success "-n mekmitasdigoat" \
authorized_keys ',principals="mekmitasdigoat"'
test_one "principals key option no principals" failure "" \
authorized_keys ',principals="mekmitasdigoat"'
# command= options vs. force-command in key
test_one "force-command match true" success \
"-n ${USER} -Oforce-command=true" \
authorized_keys ',command="true"'
test_one "force-command match true" failure \
"-n ${USER} -Oforce-command=false" \
authorized_keys ',command="false"'
test_one "force-command mismatch 1" failure \
"-n ${USER} -Oforce-command=false" \
authorized_keys ',command="true"'
test_one "force-command mismatch 2" failure \
"-n ${USER} -Oforce-command=true" \
authorized_keys ',command="false"'
# Wrong certificate
cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
for ktype in $PLAIN_TYPES ; do
t=$(kname $ktype)
# Self-sign
${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \
"regress user key for $USER" \
-n $USER $OBJ/cert_user_key_${ktype} ||
fatal "couldn't sign cert_user_key_${ktype}"
verbose "$tid: user ${ktype} connect wrong cert"
${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect $ident succeeded unexpectedly"
fi
done
rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
rm -f $OBJ/authorized_principals_$USER
diff --git a/regress/keys-command.sh b/regress/keys-command.sh
index 4029e2c78637..d166fc589d71 100755
--- a/regress/keys-command.sh
+++ b/regress/keys-command.sh
@@ -1,82 +1,81 @@
-# $OpenBSD: keys-command.sh,v 1.4 2016/09/26 21:34:38 bluhm Exp $
+# $OpenBSD: keys-command.sh,v 1.5 2018/11/22 08:48:32 dtucker Exp $
# Placed in the Public Domain.
tid="authorized keys from command"
if [ -z "$SUDO" -a ! -w /var/run ]; then
echo "skipped (SUDO not set)"
echo "need SUDO to create file in /var/run, test won't work without"
exit 0
fi
rm -f $OBJ/keys-command-args
touch $OBJ/keys-command-args
chmod a+rw $OBJ/keys-command-args
expected_key_text=`awk '{ print $2 }' < $OBJ/rsa.pub`
expected_key_fp=`$SSHKEYGEN -lf $OBJ/rsa.pub | awk '{ print $2 }'`
# Establish a AuthorizedKeysCommand in /var/run where it will have
# acceptable directory permissions.
-KEY_COMMAND="/var/run/keycommand_${LOGNAME}"
+KEY_COMMAND="/var/run/keycommand_${LOGNAME}.$$"
+trap "${SUDO} rm -f ${KEY_COMMAND}" 0
cat << _EOF | $SUDO sh -c "rm -f '$KEY_COMMAND' ; cat > '$KEY_COMMAND'"
#!/bin/sh
echo args: "\$@" >> $OBJ/keys-command-args
echo "$PATH" | grep -q mekmitasdigoat && exit 7
test "x\$1" != "x${LOGNAME}" && exit 1
if test $# -eq 6 ; then
test "x\$2" != "xblah" && exit 2
test "x\$3" != "x${expected_key_text}" && exit 3
test "x\$4" != "xssh-rsa" && exit 4
test "x\$5" != "x${expected_key_fp}" && exit 5
test "x\$6" != "xblah" && exit 6
fi
exec cat "$OBJ/authorized_keys_${LOGNAME}"
_EOF
$SUDO chmod 0755 "$KEY_COMMAND"
if ! $OBJ/check-perm -m keys-command $KEY_COMMAND ; then
echo "skipping: $KEY_COMMAND is unsuitable as AuthorizedKeysCommand"
$SUDO rm -f $KEY_COMMAND
exit 0
fi
if [ -x $KEY_COMMAND ]; then
cp $OBJ/sshd_proxy $OBJ/sshd_proxy.bak
verbose "AuthorizedKeysCommand with arguments"
(
grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak
echo AuthorizedKeysFile none
echo AuthorizedKeysCommand $KEY_COMMAND %u blah %k %t %f blah
echo AuthorizedKeysCommandUser ${LOGNAME}
) > $OBJ/sshd_proxy
# Ensure that $PATH is sanitised in sshd
env PATH=$PATH:/sbin/mekmitasdigoat \
${SSH} -F $OBJ/ssh_proxy somehost true
if [ $? -ne 0 ]; then
fail "connect failed"
fi
verbose "AuthorizedKeysCommand without arguments"
# Check legacy behavior of no-args resulting in username being passed.
(
grep -vi AuthorizedKeysFile $OBJ/sshd_proxy.bak
echo AuthorizedKeysFile none
echo AuthorizedKeysCommand $KEY_COMMAND
echo AuthorizedKeysCommandUser ${LOGNAME}
) > $OBJ/sshd_proxy
# Ensure that $PATH is sanitised in sshd
env PATH=$PATH:/sbin/mekmitasdigoat \
${SSH} -F $OBJ/ssh_proxy somehost true
if [ $? -ne 0 ]; then
fail "connect failed"
fi
else
echo "SKIPPED: $KEY_COMMAND not executable (/var/run mounted noexec?)"
fi
-
-$SUDO rm -f $KEY_COMMAND
diff --git a/regress/keyscan.sh b/regress/keyscan.sh
index 3bde1219a605..8940d24b6391 100644
--- a/regress/keyscan.sh
+++ b/regress/keyscan.sh
@@ -1,20 +1,26 @@
-# $OpenBSD: keyscan.sh,v 1.6 2017/04/30 23:34:55 djm Exp $
+# $OpenBSD: keyscan.sh,v 1.9 2019/01/28 03:50:39 dtucker Exp $
# Placed in the Public Domain.
tid="keyscan"
-# remove DSA hostkey
-rm -f ${OBJ}/host.dsa
+KEYTYPES=`${SSH} -Q key-plain`
+for i in $KEYTYPES; do
+ if [ -z "$algs" ]; then
+ algs="$i"
+ else
+ algs="$algs,$i"
+ fi
+done
+echo "HostKeyAlgorithms $algs" >> $OBJ/sshd_config
start_sshd
-KEYTYPES=`${SSH} -Q key-plain`
for t in $KEYTYPES; do
trace "keyscan type $t"
${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \
> /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-keyscan -t $t failed with: $r"
fi
done
diff --git a/regress/misc/kexfuzz/Makefile b/regress/misc/kexfuzz/Makefile
index a7bb6b70d211..20802cb87038 100644
--- a/regress/misc/kexfuzz/Makefile
+++ b/regress/misc/kexfuzz/Makefile
@@ -1,88 +1,97 @@
-# $OpenBSD: Makefile,v 1.3 2017/12/21 05:46:35 djm Exp $
+# $OpenBSD: Makefile,v 1.4 2019/01/21 12:50:12 djm Exp $
.include <bsd.own.mk>
.include <bsd.obj.mk>
# XXX detect from ssh binary?
SSH1?= no
OPENSSL?= yes
PROG= kexfuzz
SRCS= kexfuzz.c
SSHREL=../../../../../usr.bin/ssh
.PATH: ${.CURDIR}/${SSHREL}
# From usr.bin/ssh
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c ssh-dss.c
SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
SRCS+=addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c
-SRCS+=kex.c kexc25519.c kexc25519c.c kexc25519s.c kexdh.c kexdhc.c kexdhs.c
-SRCS+=kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c kexgexs.c
-SRCS+=dh.c compat.c
-SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
+SRCS+=compat.c ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c
-SRCS+=smult_curve25519_ref.c
+
+SRCS+= kex.c
+SRCS+= dh.c
+SRCS+= kexdh.c
+SRCS+= kexecdh.c
+SRCS+= kexgex.c
+SRCS+= kexgexc.c
+SRCS+= kexgexs.c
+SRCS+= kexc25519.c
+SRCS+= smult_curve25519_ref.c
+SRCS+= kexgen.c
+SRCS+= kexsntrup4591761x25519.c
+SRCS+= sntrup4591761.c
SRCS+=digest-openssl.c
#SRCS+=digest-libc.c
NOMAN= 1
.if (${OPENSSL:L} == "yes")
CFLAGS+= -DWITH_OPENSSL
.else
# SSH v.1 requires OpenSSL.
SSH1= no
.endif
.if (${SSH1:L} == "yes")
CFLAGS+= -DWITH_SSH1
.endif
# enable warnings
WARNINGS=Yes
DEBUG=-g
CFLAGS+= -fstack-protector-all
CDIAGFLAGS= -Wall
CDIAGFLAGS+= -Wextra
CDIAGFLAGS+= -Werror
CDIAGFLAGS+= -Wchar-subscripts
CDIAGFLAGS+= -Wcomment
CDIAGFLAGS+= -Wformat
CDIAGFLAGS+= -Wformat-security
CDIAGFLAGS+= -Wimplicit
CDIAGFLAGS+= -Winline
CDIAGFLAGS+= -Wmissing-declarations
CDIAGFLAGS+= -Wmissing-prototypes
CDIAGFLAGS+= -Wparentheses
CDIAGFLAGS+= -Wpointer-arith
CDIAGFLAGS+= -Wreturn-type
CDIAGFLAGS+= -Wshadow
CDIAGFLAGS+= -Wsign-compare
CDIAGFLAGS+= -Wstrict-aliasing
CDIAGFLAGS+= -Wstrict-prototypes
CDIAGFLAGS+= -Wswitch
CDIAGFLAGS+= -Wtrigraphs
CDIAGFLAGS+= -Wuninitialized
CDIAGFLAGS+= -Wunused
CDIAGFLAGS+= -Wno-unused-parameter
.if ${COMPILER_VERSION:L} != "gcc3"
CDIAGFLAGS+= -Wold-style-definition
.endif
CFLAGS+=-I${.CURDIR}/${SSHREL}
LDADD+= -lutil -lz
DPADD+= ${LIBUTIL} ${LIBZ}
.if (${OPENSSL:L} == "yes")
LDADD+= -lcrypto
DPADD+= ${LIBCRYPTO}
.endif
.include <bsd.prog.mk>
diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c
index 3e2c481606c0..7051e87b1acc 100644
--- a/regress/misc/kexfuzz/kexfuzz.c
+++ b/regress/misc/kexfuzz/kexfuzz.c
@@ -1,459 +1,457 @@
-/* $OpenBSD: kexfuzz.c,v 1.4 2017/04/30 23:34:55 djm Exp $ */
+/* $OpenBSD: kexfuzz.c,v 1.5 2019/01/21 12:50:12 djm Exp $ */
/*
* Fuzz harness for KEX code
*
* Placed in the public domain
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_ERR_H
# include <err.h>
#endif
#include "ssherr.h"
#include "ssh_api.h"
#include "sshbuf.h"
#include "packet.h"
#include "myproposal.h"
#include "authfile.h"
#include "log.h"
-struct ssh *active_state = NULL; /* XXX - needed for linking */
-
void kex_tests(void);
static int do_debug = 0;
enum direction { S2C, C2S };
struct hook_ctx {
struct ssh *client, *server, *server2;
int *c2s, *s2c;
int trigger_direction, packet_index;
const char *dump_path;
struct sshbuf *replace_data;
};
static int
packet_hook(struct ssh *ssh, struct sshbuf *packet, u_char *typep, void *_ctx)
{
struct hook_ctx *ctx = (struct hook_ctx *)_ctx;
int mydirection = ssh == ctx->client ? S2C : C2S;
int *packet_count = mydirection == S2C ? ctx->s2c : ctx->c2s;
FILE *dumpfile;
int r;
if (do_debug) {
printf("%s packet %d type %u:\n",
mydirection == S2C ? "s2c" : "c2s",
*packet_count, *typep);
sshbuf_dump(packet, stdout);
}
if (mydirection == ctx->trigger_direction &&
ctx->packet_index == *packet_count) {
if (ctx->replace_data != NULL) {
sshbuf_reset(packet);
/* Type is first byte of packet */
if ((r = sshbuf_get_u8(ctx->replace_data,
typep)) != 0 ||
(r = sshbuf_putb(packet, ctx->replace_data)) != 0)
return r;
if (do_debug) {
printf("***** replaced packet type %u\n",
*typep);
sshbuf_dump(packet, stdout);
}
} else if (ctx->dump_path != NULL) {
if ((dumpfile = fopen(ctx->dump_path, "w+")) == NULL)
err(1, "fopen %s", ctx->dump_path);
/* Write { type, packet } */
if (fwrite(typep, 1, 1, dumpfile) != 1)
err(1, "fwrite type %s", ctx->dump_path);
if (sshbuf_len(packet) != 0 &&
fwrite(sshbuf_ptr(packet), sshbuf_len(packet),
1, dumpfile) != 1)
err(1, "fwrite body %s", ctx->dump_path);
if (do_debug) {
printf("***** dumped packet type %u len %zu\n",
*typep, sshbuf_len(packet));
}
fclose(dumpfile);
/* No point in continuing */
exit(0);
}
}
(*packet_count)++;
return 0;
}
static int
do_send_and_receive(struct ssh *from, struct ssh *to)
{
u_char type;
size_t len;
const u_char *buf;
int r;
for (;;) {
if ((r = ssh_packet_next(from, &type)) != 0) {
fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
return r;
}
if (type != 0)
return 0;
buf = ssh_output_ptr(from, &len);
if (len == 0)
return 0;
if ((r = ssh_input_append(to, buf, len)) != 0) {
debug("ssh_input_append: %s", ssh_err(r));
return r;
}
if ((r = ssh_output_consume(from, len)) != 0) {
debug("ssh_output_consume: %s", ssh_err(r));
return r;
}
}
}
/* Minimal test_helper.c scaffholding to make this standalone */
const char *in_test = NULL;
#define TEST_START(a) \
do { \
in_test = (a); \
if (do_debug) \
fprintf(stderr, "test %s starting\n", in_test); \
} while (0)
#define TEST_DONE() \
do { \
if (do_debug) \
fprintf(stderr, "test %s done\n", \
in_test ? in_test : "???"); \
in_test = NULL; \
} while(0)
#define ASSERT_INT_EQ(a, b) \
do { \
if ((int)(a) != (int)(b)) { \
fprintf(stderr, "%s %s:%d " \
"%s (%d) != expected %s (%d)\n", \
in_test ? in_test : "(none)", \
__func__, __LINE__, #a, (int)(a), #b, (int)(b)); \
exit(2); \
} \
} while (0)
#define ASSERT_INT_GE(a, b) \
do { \
if ((int)(a) < (int)(b)) { \
fprintf(stderr, "%s %s:%d " \
"%s (%d) < expected %s (%d)\n", \
in_test ? in_test : "(none)", \
__func__, __LINE__, #a, (int)(a), #b, (int)(b)); \
exit(2); \
} \
} while (0)
#define ASSERT_PTR_NE(a, b) \
do { \
if ((a) == (b)) { \
fprintf(stderr, "%s %s:%d " \
"%s (%p) != expected %s (%p)\n", \
in_test ? in_test : "(none)", \
__func__, __LINE__, #a, (a), #b, (b)); \
exit(2); \
} \
} while (0)
static void
run_kex(struct ssh *client, struct ssh *server)
{
int r = 0;
while (!server->kex->done || !client->kex->done) {
if ((r = do_send_and_receive(server, client)) != 0) {
debug("do_send_and_receive S2C: %s", ssh_err(r));
break;
}
if ((r = do_send_and_receive(client, server)) != 0) {
debug("do_send_and_receive C2S: %s", ssh_err(r));
break;
}
}
if (do_debug)
printf("done: %s\n", ssh_err(r));
ASSERT_INT_EQ(r, 0);
ASSERT_INT_EQ(server->kex->done, 1);
ASSERT_INT_EQ(client->kex->done, 1);
}
static void
do_kex_with_key(const char *kex, struct sshkey *prvkey, int *c2s, int *s2c,
int direction, int packet_index,
const char *dump_path, struct sshbuf *replace_data)
{
struct ssh *client = NULL, *server = NULL, *server2 = NULL;
struct sshkey *pubkey = NULL;
struct sshbuf *state;
struct kex_params kex_params;
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
char *keyname = NULL;
struct hook_ctx hook_ctx;
TEST_START("sshkey_from_private");
ASSERT_INT_EQ(sshkey_from_private(prvkey, &pubkey), 0);
TEST_DONE();
TEST_START("ssh_init");
memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
if (kex != NULL)
kex_params.proposal[PROPOSAL_KEX_ALGS] = strdup(kex);
keyname = strdup(sshkey_ssh_name(prvkey));
ASSERT_PTR_NE(keyname, NULL);
kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
ASSERT_PTR_NE(client, NULL);
ASSERT_PTR_NE(server, NULL);
ASSERT_PTR_NE(server2, NULL);
TEST_DONE();
hook_ctx.c2s = c2s;
hook_ctx.s2c = s2c;
hook_ctx.trigger_direction = direction;
hook_ctx.packet_index = packet_index;
hook_ctx.dump_path = dump_path;
hook_ctx.replace_data = replace_data;
hook_ctx.client = client;
hook_ctx.server = server;
hook_ctx.server2 = server2;
ssh_packet_set_input_hook(client, packet_hook, &hook_ctx);
ssh_packet_set_input_hook(server, packet_hook, &hook_ctx);
ssh_packet_set_input_hook(server2, packet_hook, &hook_ctx);
TEST_START("ssh_add_hostkey");
ASSERT_INT_EQ(ssh_add_hostkey(server, prvkey), 0);
ASSERT_INT_EQ(ssh_add_hostkey(client, pubkey), 0);
TEST_DONE();
TEST_START("kex");
run_kex(client, server);
TEST_DONE();
TEST_START("rekeying client");
ASSERT_INT_EQ(kex_send_kexinit(client), 0);
run_kex(client, server);
TEST_DONE();
TEST_START("rekeying server");
ASSERT_INT_EQ(kex_send_kexinit(server), 0);
run_kex(client, server);
TEST_DONE();
TEST_START("ssh_packet_get_state");
state = sshbuf_new();
ASSERT_PTR_NE(state, NULL);
ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
ASSERT_INT_GE(sshbuf_len(state), 1);
TEST_DONE();
TEST_START("ssh_packet_set_state");
ASSERT_INT_EQ(ssh_add_hostkey(server2, prvkey), 0);
kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */
ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
ASSERT_INT_EQ(sshbuf_len(state), 0);
sshbuf_free(state);
ASSERT_PTR_NE(server2->kex, NULL);
/* XXX we need to set the callbacks */
#ifdef WITH_OPENSSL
- server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
- server2->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server;
- server2->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server;
- server2->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server;
+ server2->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ server2->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ server2->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ server2->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif
- server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
server2->kex->load_host_public_key = server->kex->load_host_public_key;
server2->kex->load_host_private_key = server->kex->load_host_private_key;
server2->kex->sign = server->kex->sign;
TEST_DONE();
TEST_START("rekeying server2");
ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
run_kex(client, server2);
ASSERT_INT_EQ(kex_send_kexinit(client), 0);
run_kex(client, server2);
TEST_DONE();
TEST_START("cleanup");
sshkey_free(pubkey);
ssh_free(client);
ssh_free(server);
ssh_free(server2);
free(keyname);
TEST_DONE();
}
static void
usage(void)
{
fprintf(stderr,
"Usage: kexfuzz [-hcdrv] [-D direction] [-f data_file]\n"
" [-K kex_alg] [-k private_key] [-i packet_index]\n"
"\n"
"Options:\n"
" -h Display this help\n"
" -c Count packets sent during KEX\n"
" -d Dump mode: record KEX packet to data file\n"
" -r Replace mode: replace packet with data file\n"
" -v Turn on verbose logging\n"
" -D S2C|C2S Packet direction for replacement or dump\n"
" -f data_file Path to data file for replacement or dump\n"
" -K kex_alg Name of KEX algorithm to test (see below)\n"
" -k private_key Path to private key file\n"
" -i packet_index Index of packet to replace or dump (from 0)\n"
"\n"
"Available KEX algorithms: %s\n", kex_alg_list(' '));
}
static void
badusage(const char *bad)
{
fprintf(stderr, "Invalid options\n");
fprintf(stderr, "%s\n", bad);
usage();
exit(1);
}
int
main(int argc, char **argv)
{
int ch, fd, r;
int count_flag = 0, dump_flag = 0, replace_flag = 0;
int packet_index = -1, direction = -1;
int s2c = 0, c2s = 0; /* packet counts */
const char *kex = NULL, *kpath = NULL, *data_path = NULL;
struct sshkey *key = NULL;
struct sshbuf *replace_data = NULL;
setvbuf(stdout, NULL, _IONBF, 0);
while ((ch = getopt(argc, argv, "hcdrvD:f:K:k:i:")) != -1) {
switch (ch) {
case 'h':
usage();
return 0;
case 'c':
count_flag = 1;
break;
case 'd':
dump_flag = 1;
break;
case 'r':
replace_flag = 1;
break;
case 'v':
do_debug = 1;
break;
case 'D':
if (strcasecmp(optarg, "s2c") == 0)
direction = S2C;
else if (strcasecmp(optarg, "c2s") == 0)
direction = C2S;
else
badusage("Invalid direction (-D)");
break;
case 'f':
data_path = optarg;
break;
case 'K':
kex = optarg;
break;
case 'k':
kpath = optarg;
break;
case 'i':
packet_index = atoi(optarg);
if (packet_index < 0)
badusage("Invalid packet index");
break;
default:
badusage("unsupported flag");
}
}
argc -= optind;
argv += optind;
log_init(argv[0], do_debug ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
SYSLOG_FACILITY_USER, 1);
/* Must select a single mode */
if ((count_flag + dump_flag + replace_flag) != 1)
badusage("Must select one mode: -c, -d or -r");
/* KEX type is mandatory */
if (kex == NULL || !kex_names_valid(kex) || strchr(kex, ',') != NULL)
badusage("Missing or invalid kex type (-K flag)");
/* Valid key is mandatory */
if (kpath == NULL)
badusage("Missing private key (-k flag)");
if ((fd = open(kpath, O_RDONLY)) == -1)
err(1, "open %s", kpath);
if ((r = sshkey_load_private_type_fd(fd, KEY_UNSPEC, NULL,
&key, NULL)) != 0)
errx(1, "Unable to load key %s: %s", kpath, ssh_err(r));
close(fd);
/* XXX check that it is a private key */
/* XXX support certificates */
if (key == NULL || key->type == KEY_UNSPEC)
badusage("Invalid key file (-k flag)");
/* Replace (fuzz) mode */
if (replace_flag) {
if (packet_index == -1 || direction == -1 || data_path == NULL)
badusage("Replace (-r) mode must specify direction "
"(-D) packet index (-i) and data path (-f)");
if ((fd = open(data_path, O_RDONLY)) == -1)
err(1, "open %s", data_path);
replace_data = sshbuf_new();
if ((r = sshkey_load_file(fd, replace_data)) != 0)
errx(1, "read %s: %s", data_path, ssh_err(r));
close(fd);
}
/* Dump mode */
if (dump_flag) {
if (packet_index == -1 || direction == -1 || data_path == NULL)
badusage("Dump (-d) mode must specify direction "
"(-D), packet index (-i) and data path (-f)");
}
/* Count mode needs no further flags */
do_kex_with_key(kex, key, &c2s, &s2c,
direction, packet_index,
dump_flag ? data_path : NULL,
replace_flag ? replace_data : NULL);
sshkey_free(key);
sshbuf_free(replace_data);
if (count_flag) {
printf("S2C: %d\n", s2c);
printf("C2S: %d\n", c2s);
}
return 0;
}
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
index a6fad8eb820c..de357c4d5edc 100644
--- a/regress/multiplex.sh
+++ b/regress/multiplex.sh
@@ -1,191 +1,193 @@
-# $OpenBSD: multiplex.sh,v 1.28 2017/04/30 23:34:55 djm Exp $
+# $OpenBSD: multiplex.sh,v 1.29 2019/01/01 22:20:16 djm Exp $
# Placed in the Public Domain.
make_tmpdir
CTL=${SSH_REGRESS_TMP}/ctl-sock
tid="connection multiplexing"
NC=$OBJ/netcat
trace "will use ProxyCommand $proxycmd"
if config_defined DISABLE_FD_PASSING ; then
echo "skipped (not supported on this platform)"
exit 0
fi
P=3301 # test port
wait_for_mux_master_ready()
{
for i in 1 2 3 4 5; do
${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost \
>/dev/null 2>&1 && return 0
sleep $i
done
fatal "mux master never becomes ready"
}
start_sshd
start_mux_master()
{
trace "start master, fork to background"
${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \
-E $TEST_REGRESS_LOGFILE 2>&1 &
# NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors.
SSH_PID=$!
wait_for_mux_master_ready
}
start_mux_master
verbose "test $tid: envpass"
trace "env passing over multiplexed connection"
_XXX_TEST=blah ${SSH} -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" -S$CTL otherhost sh << 'EOF'
test X"$_XXX_TEST" = X"blah"
EOF
if [ $? -ne 0 ]; then
fail "environment not found"
fi
verbose "test $tid: transfer"
rm -f ${COPY}
trace "ssh transfer over multiplexed connection and check result"
${SSH} -F $OBJ/ssh_config -S$CTL otherhost cat ${DATA} > ${COPY}
test -f ${COPY} || fail "ssh -Sctl: failed copy ${DATA}"
cmp ${DATA} ${COPY} || fail "ssh -Sctl: corrupted copy of ${DATA}"
rm -f ${COPY}
trace "ssh transfer over multiplexed connection and check result"
${SSH} -F $OBJ/ssh_config -S $CTL otherhost cat ${DATA} > ${COPY}
test -f ${COPY} || fail "ssh -S ctl: failed copy ${DATA}"
cmp ${DATA} ${COPY} || fail "ssh -S ctl: corrupted copy of ${DATA}"
rm -f ${COPY}
trace "sftp transfer over multiplexed connection and check result"
echo "get ${DATA} ${COPY}" | \
${SFTP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost >>$TEST_REGRESS_LOGFILE 2>&1
test -f ${COPY} || fail "sftp: failed copy ${DATA}"
cmp ${DATA} ${COPY} || fail "sftp: corrupted copy of ${DATA}"
rm -f ${COPY}
trace "scp transfer over multiplexed connection and check result"
${SCP} -S ${SSH} -F $OBJ/ssh_config -oControlPath=$CTL otherhost:${DATA} ${COPY} >>$TEST_REGRESS_LOGFILE 2>&1
test -f ${COPY} || fail "scp: failed copy ${DATA}"
cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
rm -f ${COPY}
verbose "test $tid: forward"
trace "forward over TCP/IP and check result"
$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
netcat_pid=$!
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1
$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
kill $netcat_pid 2>/dev/null
rm -f ${COPY} $OBJ/unix-[123].fwd
trace "forward over UNIX and check result"
$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
netcat_pid=$!
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY} 2>/dev/null
cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
kill $netcat_pid 2>/dev/null
rm -f ${COPY} $OBJ/unix-[123].fwd
for s in 0 1 4 5 44; do
trace "exit status $s over multiplexed connection"
verbose "test $tid: status $s"
${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s
r=$?
if [ $r -ne $s ]; then
fail "exit code mismatch: $r != $s"
fi
# same with early close of stdout/err
trace "exit status $s with early close over multiplexed connection"
${SSH} -F $OBJ/ssh_config -S $CTL -n otherhost \
exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
r=$?
if [ $r -ne $s ]; then
fail "exit code (with sleep) mismatch: $r != $s"
fi
done
verbose "test $tid: cmd check"
${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
|| fail "check command failed"
verbose "test $tid: cmd forward local (TCP)"
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \
|| fail "request local forward failed"
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
|| fail "connect to local forward port failed"
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \
|| fail "cancel local forward failed"
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
&& fail "local forward port still listening"
verbose "test $tid: cmd forward remote (TCP)"
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \
|| fail "request remote forward failed"
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
|| fail "connect to remote forwarded port failed"
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \
|| fail "cancel remote forward failed"
${SSH} -F $OBJ/ssh_config -p$P otherhost true \
&& fail "remote forward port still listening"
verbose "test $tid: cmd forward local (UNIX)"
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|| fail "request local forward failed"
-echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \
+echo "" | $NC -U $OBJ/unix-1.fwd | \
+ grep "Invalid SSH identification string" >/dev/null 2>&1 \
|| fail "connect to local forward path failed"
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|| fail "cancel local forward failed"
N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
test ${N} -eq 0 || fail "local forward path still listening"
rm -f $OBJ/unix-1.fwd
verbose "test $tid: cmd forward remote (UNIX)"
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|| fail "request remote forward failed"
-echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \
+echo "" | $NC -U $OBJ/unix-1.fwd | \
+ grep "Invalid SSH identification string" >/dev/null 2>&1 \
|| fail "connect to remote forwarded path failed"
${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
|| fail "cancel remote forward failed"
N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
test ${N} -eq 0 || fail "remote forward path still listening"
rm -f $OBJ/unix-1.fwd
verbose "test $tid: cmd exit"
${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
|| fail "send exit command failed"
# Wait for master to exit
wait $SSH_PID
kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed"
# Restart master and test -O stop command with master using -N
verbose "test $tid: cmd stop"
trace "restart master, fork to background"
start_mux_master
# start a long-running command then immediately request a stop
${SSH} -F $OBJ/ssh_config -S $CTL otherhost "sleep 10; exit 0" \
>>$TEST_REGRESS_LOGFILE 2>&1 &
SLEEP_PID=$!
${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
|| fail "send stop command failed"
# wait until both long-running command and master have exited.
wait $SLEEP_PID
[ $! != 0 ] || fail "waiting for concurrent command"
wait $SSH_PID
[ $! != 0 ] || fail "waiting for master stop"
kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed"
SSH_PID="" # Already gone, so don't kill in cleanup
diff --git a/regress/multipubkey.sh b/regress/multipubkey.sh
index e9d15306ff2f..4d443ec45da3 100755
--- a/regress/multipubkey.sh
+++ b/regress/multipubkey.sh
@@ -1,66 +1,66 @@
-# $OpenBSD: multipubkey.sh,v 1.1 2014/12/22 08:06:03 djm Exp $
+# $OpenBSD: multipubkey.sh,v 1.2 2018/10/31 11:09:27 dtucker Exp $
# Placed in the Public Domain.
tid="multiple pubkey"
rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
# Create a CA key
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\
fatal "ssh-keygen failed"
# Make some keys and a certificate.
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
fatal "ssh-keygen failed"
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
fatal "ssh-keygen failed"
${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
-z $$ -n ${USER},mekmitasdigoat $OBJ/user_key1 ||
fail "couldn't sign user_key1"
# Copy the private key alongside the cert to allow better control of when
# it is offered.
mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1.pub
cp -p $OBJ/user_key1 $OBJ/cert_user_key1
grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2"
-for privsep in no yes; do
+for privsep in yes sandbox ; do
(
grep -v "Protocol" $OBJ/sshd_proxy.orig
echo "Protocol 2"
echo "UsePrivilegeSeparation $privsep"
echo "AuthenticationMethods publickey,publickey"
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
) > $OBJ/sshd_proxy
# Single key should fail.
rm -f $OBJ/authorized_principals_$USER
cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
${SSH} $opts proxy true && fail "ssh succeeded with key"
# Single key with same-public cert should fail.
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
${SSH} $opts proxy true && fail "ssh succeeded with key+cert"
# Multiple plain keys should succeed.
rm -f $OBJ/authorized_principals_$USER
cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \
$OBJ/authorized_keys_$USER
${SSH} $opts proxy true || fail "ssh failed with multiple keys"
# Cert and different key should succeed
# Key and different-public cert should succeed.
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER
${SSH} $opts proxy true || fail "ssh failed with key/cert"
done
diff --git a/regress/principals-command.sh b/regress/principals-command.sh
index bcc68e80bca6..197c0002170b 100755
--- a/regress/principals-command.sh
+++ b/regress/principals-command.sh
@@ -1,168 +1,169 @@
-# $OpenBSD: principals-command.sh,v 1.4 2017/04/30 23:34:55 djm Exp $
+# $OpenBSD: principals-command.sh,v 1.6 2018/11/22 08:48:32 dtucker Exp $
# Placed in the Public Domain.
tid="authorized principals command"
rm -f $OBJ/user_ca_key* $OBJ/cert_user_key*
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
if [ -z "$SUDO" -a ! -w /var/run ]; then
echo "skipped (SUDO not set)"
echo "need SUDO to create file in /var/run, test won't work without"
exit 0
fi
SERIAL=$$
# Create a CA key and a user certificate.
${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key || \
fatal "ssh-keygen of user_ca_key failed"
${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/cert_user_key || \
fatal "ssh-keygen of cert_user_key failed"
${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "Joanne User" \
-z $$ -n ${USER},mekmitasdigoat $OBJ/cert_user_key || \
fatal "couldn't sign cert_user_key"
CERT_BODY=`cat $OBJ/cert_user_key-cert.pub | awk '{ print $2 }'`
CA_BODY=`cat $OBJ/user_ca_key.pub | awk '{ print $2 }'`
CERT_FP=`${SSHKEYGEN} -lf $OBJ/cert_user_key-cert.pub | awk '{ print $2 }'`
CA_FP=`${SSHKEYGEN} -lf $OBJ/user_ca_key.pub | awk '{ print $2 }'`
# Establish a AuthorizedPrincipalsCommand in /var/run where it will have
# acceptable directory permissions.
-PRINCIPALS_COMMAND="/var/run/principals_command_${LOGNAME}"
+PRINCIPALS_COMMAND="/var/run/principals_command_${LOGNAME}.$$"
+trap "$SUDO rm -f ${PRINCIPALS_COMMAND}" 0
cat << _EOF | $SUDO sh -c "cat > '$PRINCIPALS_COMMAND'"
#!/bin/sh
test "x\$1" != "x${LOGNAME}" && exit 1
test "x\$2" != "xssh-rsa-cert-v01@openssh.com" && exit 1
test "x\$3" != "xssh-ed25519" && exit 1
test "x\$4" != "xJoanne User" && exit 1
test "x\$5" != "x${SERIAL}" && exit 1
test "x\$6" != "x${CA_FP}" && exit 1
test "x\$7" != "x${CERT_FP}" && exit 1
test "x\$8" != "x${CERT_BODY}" && exit 1
test "x\$9" != "x${CA_BODY}" && exit 1
test -f "$OBJ/authorized_principals_${LOGNAME}" &&
exec cat "$OBJ/authorized_principals_${LOGNAME}"
_EOF
test $? -eq 0 || fatal "couldn't prepare principals command"
$SUDO chmod 0755 "$PRINCIPALS_COMMAND"
if ! $OBJ/check-perm -m keys-command $PRINCIPALS_COMMAND ; then
echo "skipping: $PRINCIPALS_COMMAND is unsuitable as " \
"AuthorizedPrincipalsCommand"
$SUDO rm -f $PRINCIPALS_COMMAND
exit 0
fi
if [ -x $PRINCIPALS_COMMAND ]; then
# Test explicitly-specified principals
- for privsep in yes no ; do
+ for privsep in yes sandbox ; do
_prefix="privsep $privsep"
# Setup for AuthorizedPrincipalsCommand
rm -f $OBJ/authorized_keys_$USER
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
echo "AuthorizedKeysFile none"
echo "AuthorizedPrincipalsCommand $PRINCIPALS_COMMAND" \
"%u %t %T %i %s %F %f %k %K"
echo "AuthorizedPrincipalsCommandUser ${LOGNAME}"
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
) > $OBJ/sshd_proxy
# XXX test missing command
# XXX test failing command
# Empty authorized_principals
verbose "$tid: ${_prefix} empty authorized_principals"
echo > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Wrong authorized_principals
verbose "$tid: ${_prefix} wrong authorized_principals"
echo gregorsamsa > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Correct authorized_principals
verbose "$tid: ${_prefix} correct authorized_principals"
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
# authorized_principals with bad key option
verbose "$tid: ${_prefix} authorized_principals bad key opt"
echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# authorized_principals with command=false
verbose "$tid: ${_prefix} authorized_principals command=false"
echo 'command="false" mekmitasdigoat' > \
$OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# authorized_principals with command=true
verbose "$tid: ${_prefix} authorized_principals command=true"
echo 'command="true" mekmitasdigoat' > \
$OBJ/authorized_principals_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
# Setup for principals= key option
rm -f $OBJ/authorized_principals_$USER
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
) > $OBJ/sshd_proxy
# Wrong principals list
verbose "$tid: ${_prefix} wrong principals key option"
(
printf 'cert-authority,principals="gregorsamsa" '
cat $OBJ/user_ca_key.pub
) > $OBJ/authorized_keys_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
fail "ssh cert connect succeeded unexpectedly"
fi
# Correct principals list
verbose "$tid: ${_prefix} correct principals key option"
(
printf 'cert-authority,principals="mekmitasdigoat" '
cat $OBJ/user_ca_key.pub
) > $OBJ/authorized_keys_$USER
${SSH} -i $OBJ/cert_user_key \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
done
else
echo "SKIPPED: $PRINCIPALS_COMMAND not executable " \
"(/var/run mounted noexec?)"
fi
diff --git a/regress/sftp-chroot.sh b/regress/sftp-chroot.sh
index ba5bd1efb30e..5acc4d2de4a6 100755
--- a/regress/sftp-chroot.sh
+++ b/regress/sftp-chroot.sh
@@ -1,32 +1,31 @@
-# $OpenBSD: sftp-chroot.sh,v 1.6 2018/02/09 03:42:57 dtucker Exp $
+# $OpenBSD: sftp-chroot.sh,v 1.7 2018/11/22 08:48:32 dtucker Exp $
# Placed in the Public Domain.
tid="sftp in chroot"
CHROOT=/var/run
-FILENAME=testdata_${USER}
+FILENAME=testdata_${USER}.$$
PRIVDATA=${CHROOT}/${FILENAME}
+trap "${SUDO} rm -f ${PRIVDATA}" 0
if [ -z "$SUDO" -a ! -w /var/run ]; then
echo "need SUDO to create file in /var/run, test won't work without"
echo SKIPPED
exit 0
fi
if ! $OBJ/check-perm -m chroot "$CHROOT" ; then
echo "skipped: $CHROOT is unsuitable as ChrootDirectory"
exit 0
fi
$SUDO sh -c "echo mekmitastdigoat > $PRIVDATA" || \
fatal "create $PRIVDATA failed"
start_sshd -oChrootDirectory=$CHROOT -oForceCommand="internal-sftp -d /"
verbose "test $tid: get"
${SFTP} -S "$SSH" -F $OBJ/ssh_config host:/${FILENAME} $COPY \
>>$TEST_REGRESS_LOGFILE 2>&1 || \
fatal "Fetch ${FILENAME} failed"
cmp $PRIVDATA $COPY || fail "$PRIVDATA $COPY differ"
-
-$SUDO rm $PRIVDATA
diff --git a/regress/sftp-cmds.sh b/regress/sftp-cmds.sh
index aad7fcac2325..1289c4089c6c 100644
--- a/regress/sftp-cmds.sh
+++ b/regress/sftp-cmds.sh
@@ -1,232 +1,228 @@
# $OpenBSD: sftp-cmds.sh,v 1.14 2013/06/21 02:26:26 djm Exp $
# Placed in the Public Domain.
# XXX - TODO:
# - chmod / chown / chgrp
# - -p flag for get & put
tid="sftp commands"
# test that these files are readable!
for i in `(cd /bin;echo l*)`
do
if [ -r $i ]; then
GLOBFILES="$GLOBFILES $i"
fi
done
# Path with embedded quote
QUOTECOPY=${COPY}".\"blah\""
QUOTECOPY_ARG=${COPY}'.\"blah\"'
# File with spaces
SPACECOPY="${COPY} this has spaces.txt"
SPACECOPY_ARG="${COPY}\ this\ has\ spaces.txt"
# File with glob metacharacters
GLOBMETACOPY="${COPY} [metachar].txt"
rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
mkdir ${COPY}.dd
verbose "$tid: lls"
(echo "lcd ${OBJ}" ; echo "lls") | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
grep copy.dd >/dev/null 2>&1 || fail "lls failed"
verbose "$tid: lls w/path"
echo "lls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
grep copy.dd >/dev/null 2>&1 || fail "lls w/path failed"
verbose "$tid: ls"
echo "ls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "ls failed"
# XXX always successful
verbose "$tid: shell"
echo "!echo hi there" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "shell failed"
# XXX always successful
verbose "$tid: pwd"
echo "pwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "pwd failed"
# XXX always successful
verbose "$tid: lpwd"
echo "lpwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "lpwd failed"
# XXX always successful
verbose "$tid: quit"
echo "quit" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "quit failed"
# XXX always successful
verbose "$tid: help"
echo "help" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "help failed"
# XXX always successful
rm -f ${COPY}
verbose "$tid: get"
echo "get $DATA $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp $DATA ${COPY} || fail "corrupted copy after get"
rm -f ${COPY}
verbose "$tid: get quoted"
echo "get \"$DATA\" $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp $DATA ${COPY} || fail "corrupted copy after get"
-if [ "$os" != "cygwin" ]; then
rm -f ${QUOTECOPY}
cp $DATA ${QUOTECOPY}
verbose "$tid: get filename with quotes"
echo "get \"$QUOTECOPY_ARG\" ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp ${COPY} ${QUOTECOPY} || fail "corrupted copy after get with quotes"
rm -f ${QUOTECOPY} ${COPY}
-fi
rm -f "$SPACECOPY" ${COPY}
cp $DATA "$SPACECOPY"
verbose "$tid: get filename with spaces"
echo "get ${SPACECOPY_ARG} ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp ${COPY} "$SPACECOPY" || fail "corrupted copy after get with spaces"
rm -f "$GLOBMETACOPY" ${COPY}
cp $DATA "$GLOBMETACOPY"
verbose "$tid: get filename with glob metacharacters"
echo "get \"${GLOBMETACOPY}\" ${COPY}" | \
${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "get failed"
cmp ${COPY} "$GLOBMETACOPY" || \
fail "corrupted copy after get with glob metacharacters"
rm -f ${COPY}.dd/*
verbose "$tid: get to directory"
echo "get $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after get"
rm -f ${COPY}.dd/*
verbose "$tid: glob get to directory"
echo "get /bin/l* ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
done
rm -f ${COPY}.dd/*
verbose "$tid: get to local dir"
(echo "lcd ${COPY}.dd"; echo "get $DATA" ) | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after get"
rm -f ${COPY}.dd/*
verbose "$tid: glob get to local dir"
(echo "lcd ${COPY}.dd"; echo "get /bin/l*") | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "get failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
done
rm -f ${COPY}
verbose "$tid: put"
echo "put $DATA $COPY" | \
${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
cmp $DATA ${COPY} || fail "corrupted copy after put"
-if [ "$os" != "cygwin" ]; then
rm -f ${QUOTECOPY}
verbose "$tid: put filename with quotes"
echo "put $DATA \"$QUOTECOPY_ARG\"" | \
${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
cmp $DATA ${QUOTECOPY} || fail "corrupted copy after put with quotes"
-fi
rm -f "$SPACECOPY"
verbose "$tid: put filename with spaces"
echo "put $DATA ${SPACECOPY_ARG}" | \
${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
cmp $DATA "$SPACECOPY" || fail "corrupted copy after put with spaces"
rm -f ${COPY}.dd/*
verbose "$tid: put to directory"
echo "put $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "put failed"
cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after put"
rm -f ${COPY}.dd/*
verbose "$tid: glob put to directory"
echo "put /bin/l? ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "put failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
done
rm -f ${COPY}.dd/*
verbose "$tid: put to local dir"
(echo "cd ${COPY}.dd"; echo "put $DATA") | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "put failed"
cmp $DATA ${COPY}.dd/$DATANAME || fail "corrupted copy after put"
rm -f ${COPY}.dd/*
verbose "$tid: glob put to local dir"
(echo "cd ${COPY}.dd"; echo "put /bin/l?") | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "put failed"
for x in $GLOBFILES; do
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
done
verbose "$tid: rename"
echo "rename $COPY ${COPY}.1" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "rename failed"
test -f ${COPY}.1 || fail "missing file after rename"
cmp $DATA ${COPY}.1 >/dev/null 2>&1 || fail "corrupted copy after rename"
verbose "$tid: rename directory"
echo "rename ${COPY}.dd ${COPY}.dd2" | \
${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || \
fail "rename directory failed"
test -d ${COPY}.dd && fail "oldname exists after rename directory"
test -d ${COPY}.dd2 || fail "missing newname after rename directory"
verbose "$tid: ln"
echo "ln ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln failed"
test -f ${COPY}.2 || fail "missing file after ln"
cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after ln"
verbose "$tid: ln -s"
rm -f ${COPY}.2
echo "ln -s ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln -s failed"
test -h ${COPY}.2 || fail "missing file after ln -s"
verbose "$tid: mkdir"
echo "mkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "mkdir failed"
test -d ${COPY}.dd || fail "missing directory after mkdir"
# XXX do more here
verbose "$tid: chdir"
echo "chdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "chdir failed"
verbose "$tid: rmdir"
echo "rmdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "rmdir failed"
test -d ${COPY}.1 && fail "present directory after rmdir"
verbose "$tid: lmkdir"
echo "lmkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "lmkdir failed"
test -d ${COPY}.dd || fail "missing directory after lmkdir"
# XXX do more here
verbose "$tid: lchdir"
echo "lchdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|| fail "lchdir failed"
rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
rm -rf ${QUOTECOPY} "$SPACECOPY" "$GLOBMETACOPY"
diff --git a/regress/test-exec.sh b/regress/test-exec.sh
index 40d46e3cd4ca..b8e2009de8f9 100644
--- a/regress/test-exec.sh
+++ b/regress/test-exec.sh
@@ -1,593 +1,589 @@
-# $OpenBSD: test-exec.sh,v 1.64 2018/08/10 01:35:49 dtucker Exp $
+# $OpenBSD: test-exec.sh,v 1.65 2019/01/27 06:30:53 dtucker Exp $
# Placed in the Public Domain.
#SUDO=sudo
# Unbreak GNU head(1)
_POSIX2_VERSION=199209
export _POSIX2_VERSION
case `uname -s 2>/dev/null` in
OSF1*)
BIN_SH=xpg4
export BIN_SH
;;
-CYGWIN_NT-5.0)
- os=cygwin
- TEST_SSH_IPV6=no
- ;;
CYGWIN*)
os=cygwin
;;
esac
if [ ! -z "$TEST_SSH_PORT" ]; then
PORT="$TEST_SSH_PORT"
else
PORT=4242
fi
if [ -x /usr/ucb/whoami ]; then
USER=`/usr/ucb/whoami`
elif whoami >/dev/null 2>&1; then
USER=`whoami`
elif logname >/dev/null 2>&1; then
USER=`logname`
else
USER=`id -un`
fi
OBJ=$1
if [ "x$OBJ" = "x" ]; then
echo '$OBJ not defined'
exit 2
fi
if [ ! -d $OBJ ]; then
echo "not a directory: $OBJ"
exit 2
fi
SCRIPT=$2
if [ "x$SCRIPT" = "x" ]; then
echo '$SCRIPT not defined'
exit 2
fi
if [ ! -f $SCRIPT ]; then
echo "not a file: $SCRIPT"
exit 2
fi
if $TEST_SHELL -n $SCRIPT; then
true
else
echo "syntax error in $SCRIPT"
exit 2
fi
unset SSH_AUTH_SOCK
SRC=`dirname ${SCRIPT}`
# defaults
SSH=ssh
SSHD=sshd
SSHAGENT=ssh-agent
SSHADD=ssh-add
SSHKEYGEN=ssh-keygen
SSHKEYSCAN=ssh-keyscan
SFTP=sftp
SFTPSERVER=/usr/libexec/openssh/sftp-server
SCP=scp
# Set by make_tmpdir() on demand (below).
SSH_REGRESS_TMP=
# Interop testing
PLINK=plink
PUTTYGEN=puttygen
CONCH=conch
if [ "x$TEST_SSH_SSH" != "x" ]; then
SSH="${TEST_SSH_SSH}"
fi
if [ "x$TEST_SSH_SSHD" != "x" ]; then
SSHD="${TEST_SSH_SSHD}"
fi
if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then
SSHAGENT="${TEST_SSH_SSHAGENT}"
fi
if [ "x$TEST_SSH_SSHADD" != "x" ]; then
SSHADD="${TEST_SSH_SSHADD}"
fi
if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then
SSHKEYGEN="${TEST_SSH_SSHKEYGEN}"
fi
if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then
SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}"
fi
if [ "x$TEST_SSH_SFTP" != "x" ]; then
SFTP="${TEST_SSH_SFTP}"
fi
if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then
SFTPSERVER="${TEST_SSH_SFTPSERVER}"
fi
if [ "x$TEST_SSH_SCP" != "x" ]; then
SCP="${TEST_SSH_SCP}"
fi
if [ "x$TEST_SSH_PLINK" != "x" ]; then
# Find real binary, if it exists
case "${TEST_SSH_PLINK}" in
/*) PLINK="${TEST_SSH_PLINK}" ;;
*) PLINK=`which ${TEST_SSH_PLINK} 2>/dev/null` ;;
esac
fi
if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then
# Find real binary, if it exists
case "${TEST_SSH_PUTTYGEN}" in
/*) PUTTYGEN="${TEST_SSH_PUTTYGEN}" ;;
*) PUTTYGEN=`which ${TEST_SSH_PUTTYGEN} 2>/dev/null` ;;
esac
fi
if [ "x$TEST_SSH_CONCH" != "x" ]; then
# Find real binary, if it exists
case "${TEST_SSH_CONCH}" in
/*) CONCH="${TEST_SSH_CONCH}" ;;
*) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;;
esac
fi
# Path to sshd must be absolute for rexec
case "$SSHD" in
/*) ;;
*) SSHD=`which $SSHD` ;;
esac
case "$SSHAGENT" in
/*) ;;
*) SSHAGENT=`which $SSHAGENT` ;;
esac
# Record the actual binaries used.
SSH_BIN=${SSH}
SSHD_BIN=${SSHD}
SSHAGENT_BIN=${SSHAGENT}
SSHADD_BIN=${SSHADD}
SSHKEYGEN_BIN=${SSHKEYGEN}
SSHKEYSCAN_BIN=${SSHKEYSCAN}
SFTP_BIN=${SFTP}
SFTPSERVER_BIN=${SFTPSERVER}
SCP_BIN=${SCP}
if [ "x$USE_VALGRIND" != "x" ]; then
mkdir -p $OBJ/valgrind-out
VG_TEST=`basename $SCRIPT .sh`
# Some tests are difficult to fix.
case "$VG_TEST" in
connect-privsep|reexec)
VG_SKIP=1 ;;
esac
if [ x"$VG_SKIP" = "x" ]; then
VG_LEAK="--leak-check=no"
if [ x"$VALGRIND_CHECK_LEAKS" != "x" ]; then
VG_LEAK="--leak-check=full"
fi
VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*"
VG_LOG="$OBJ/valgrind-out/${VG_TEST}."
VG_OPTS="--track-origins=yes $VG_LEAK"
VG_OPTS="$VG_OPTS --trace-children=yes"
VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}"
VG_PATH="valgrind"
if [ "x$VALGRIND_PATH" != "x" ]; then
VG_PATH="$VALGRIND_PATH"
fi
VG="$VG_PATH $VG_OPTS"
SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH"
SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD"
SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT"
SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD"
SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN"
SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN"
SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}"
SCP="$VG --log-file=${VG_LOG}scp.%p $SCP"
cat > $OBJ/valgrind-sftp-server.sh << EOF
#!/bin/sh
exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@"
EOF
chmod a+rx $OBJ/valgrind-sftp-server.sh
SFTPSERVER="$OBJ/valgrind-sftp-server.sh"
fi
fi
# Logfiles.
# SSH_LOGFILE should be the debug output of ssh(1) only
# SSHD_LOGFILE should be the debug output of sshd(8) only
# REGRESS_LOGFILE is the output of the test itself stdout and stderr
if [ "x$TEST_SSH_LOGFILE" = "x" ]; then
TEST_SSH_LOGFILE=$OBJ/ssh.log
fi
if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then
TEST_SSHD_LOGFILE=$OBJ/sshd.log
fi
if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then
TEST_REGRESS_LOGFILE=$OBJ/regress.log
fi
# truncate logfiles
>$TEST_SSH_LOGFILE
>$TEST_SSHD_LOGFILE
>$TEST_REGRESS_LOGFILE
# Create wrapper ssh with logging. We can't just specify "SSH=ssh -E..."
# because sftp and scp don't handle spaces in arguments.
SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
echo "#!/bin/sh" > $SSHLOGWRAP
echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
chmod a+rx $OBJ/ssh-log-wrapper.sh
REAL_SSH="$SSH"
SSH="$SSHLOGWRAP"
# Some test data. We make a copy because some tests will overwrite it.
# The tests may assume that $DATA exists and is writable and $COPY does
# not exist. Tests requiring larger data files can call increase_datafile_size
# [kbytes] to ensure the file is at least that large.
DATANAME=data
DATA=$OBJ/${DATANAME}
cat ${SSHAGENT_BIN} >${DATA}
chmod u+w ${DATA}
COPY=$OBJ/copy
rm -f ${COPY}
increase_datafile_size()
{
while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do
cat ${SSHAGENT_BIN} >>${DATA}
done
}
# these should be used in tests
export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP
#echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP
# Portable specific functions
have_prog()
{
saved_IFS="$IFS"
IFS=":"
for i in $PATH
do
if [ -x $i/$1 ]; then
IFS="$saved_IFS"
return 0
fi
done
IFS="$saved_IFS"
return 1
}
jot() {
awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }"
}
# Check whether preprocessor symbols are defined in config.h.
config_defined ()
{
str=$1
while test "x$2" != "x" ; do
str="$str|$2"
shift
done
egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1
}
md5 () {
if have_prog md5sum; then
md5sum
elif have_prog openssl; then
openssl md5
elif have_prog cksum; then
cksum
elif have_prog sum; then
sum
else
wc -c
fi
}
# End of portable specific functions
stop_sshd ()
{
if [ -f $PIDFILE ]; then
pid=`$SUDO cat $PIDFILE`
if [ "X$pid" = "X" ]; then
echo no sshd running
else
if [ $pid -lt 2 ]; then
echo bad pid for sshd: $pid
else
$SUDO kill $pid
trace "wait for sshd to exit"
i=0;
while [ -f $PIDFILE -a $i -lt 5 ]; do
i=`expr $i + 1`
sleep $i
done
if test -f $PIDFILE; then
if $SUDO kill -0 $pid; then
echo "sshd didn't exit " \
"port $PORT pid $pid"
else
echo "sshd died without cleanup"
fi
exit 1
fi
fi
fi
fi
}
make_tmpdir ()
{
SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
fatal "failed to create temporary directory"
}
# helper
cleanup ()
{
if [ "x$SSH_PID" != "x" ]; then
if [ $SSH_PID -lt 2 ]; then
echo bad pid for ssh: $SSH_PID
else
kill $SSH_PID
fi
fi
if [ "x$SSH_REGRESS_TMP" != "x" ]; then
rm -rf "$SSH_REGRESS_TMP"
fi
stop_sshd
}
start_debug_log ()
{
echo "trace: $@" >$TEST_REGRESS_LOGFILE
echo "trace: $@" >$TEST_SSH_LOGFILE
echo "trace: $@" >$TEST_SSHD_LOGFILE
}
save_debug_log ()
{
echo $@ >>$TEST_REGRESS_LOGFILE
echo $@ >>$TEST_SSH_LOGFILE
echo $@ >>$TEST_SSHD_LOGFILE
(cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log
(cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log
(cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log
}
trace ()
{
start_debug_log $@
if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then
echo "$@"
fi
}
verbose ()
{
start_debug_log $@
if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then
echo "$@"
fi
}
warn ()
{
echo "WARNING: $@" >>$TEST_SSH_LOGFILE
echo "WARNING: $@"
}
fail ()
{
save_debug_log "FAIL: $@"
RESULT=1
echo "$@"
if test "x$TEST_SSH_FAIL_FATAL" != "x" ; then
cleanup
exit $RESULT
fi
}
fatal ()
{
save_debug_log "FATAL: $@"
printf "FATAL: "
fail "$@"
cleanup
exit $RESULT
}
RESULT=0
PIDFILE=$OBJ/pidfile
trap fatal 3 2
# create server config
cat << EOF > $OBJ/sshd_config
StrictModes no
Port $PORT
AddressFamily inet
ListenAddress 127.0.0.1
#ListenAddress ::1
PidFile $PIDFILE
AuthorizedKeysFile $OBJ/authorized_keys_%u
LogLevel DEBUG3
AcceptEnv _XXX_TEST_*
AcceptEnv _XXX_TEST
Subsystem sftp $SFTPSERVER
EOF
# This may be necessary if /usr/src and/or /usr/obj are group-writable,
# but if you aren't careful with permissions then the unit tests could
# be abused to locally escalate privileges.
if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then
echo "StrictModes no" >> $OBJ/sshd_config
fi
if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then
trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS"
echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config
fi
# server config for proxy connects
cp $OBJ/sshd_config $OBJ/sshd_proxy
# allow group-writable directories in proxy-mode
echo 'StrictModes no' >> $OBJ/sshd_proxy
# create client config
cat << EOF > $OBJ/ssh_config
Host *
Hostname 127.0.0.1
HostKeyAlias localhost-with-alias
Port $PORT
User $USER
GlobalKnownHostsFile $OBJ/known_hosts
UserKnownHostsFile $OBJ/known_hosts
PubkeyAuthentication yes
ChallengeResponseAuthentication no
HostbasedAuthentication no
PasswordAuthentication no
BatchMode yes
StrictHostKeyChecking yes
LogLevel DEBUG3
EOF
if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then
trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS"
echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config
fi
rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
-SSH_KEYTYPES="rsa ed25519"
+SSH_KEYTYPES=`$SSH -Q key-plain`
-trace "generate keys"
for t in ${SSH_KEYTYPES}; do
# generate user key
+ trace "generating key type $t"
if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then
rm -f $OBJ/$t
${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\
fail "ssh-keygen for $t failed"
fi
# known hosts file for client
(
printf 'localhost-with-alias,127.0.0.1,::1 '
cat $OBJ/$t.pub
) >> $OBJ/known_hosts
# setup authorized keys
cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
echo IdentityFile $OBJ/$t >> $OBJ/ssh_config
# use key as host key, too
$SUDO cp $OBJ/$t $OBJ/host.$t
echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
# don't use SUDO for proxy connect
echo HostKey $OBJ/$t >> $OBJ/sshd_proxy
done
chmod 644 $OBJ/authorized_keys_$USER
# Activate Twisted Conch tests if the binary is present
REGRESS_INTEROP_CONCH=no
if test -x "$CONCH" ; then
REGRESS_INTEROP_CONCH=yes
fi
# If PuTTY is present and we are running a PuTTY test, prepare keys and
# configuration
REGRESS_INTEROP_PUTTY=no
if test -x "$PUTTYGEN" -a -x "$PLINK" ; then
REGRESS_INTEROP_PUTTY=yes
fi
case "$SCRIPT" in
*putty*) ;;
*) REGRESS_INTEROP_PUTTY=no ;;
esac
if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
mkdir -p ${OBJ}/.putty
# Add a PuTTY key to authorized_keys
rm -f ${OBJ}/putty.rsa2
if ! puttygen -t rsa -o ${OBJ}/putty.rsa2 \
--random-device=/dev/urandom \
--new-passphrase /dev/null < /dev/null > /dev/null; then
echo "Your installed version of PuTTY is too old to support --new-passphrase; trying without (may require manual interaction) ..." >&2
puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null
fi
puttygen -O public-openssh ${OBJ}/putty.rsa2 \
>> $OBJ/authorized_keys_$USER
# Convert rsa2 host key to PuTTY format
cp $OBJ/rsa $OBJ/rsa_oldfmt
${SSHKEYGEN} -p -N '' -m PEM -f $OBJ/rsa_oldfmt >/dev/null
${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/rsa_oldfmt > \
${OBJ}/.putty/sshhostkeys
${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/rsa_oldfmt >> \
${OBJ}/.putty/sshhostkeys
rm -f $OBJ/rsa_oldfmt
# Setup proxied session
mkdir -p ${OBJ}/.putty/sessions
rm -f ${OBJ}/.putty/sessions/localhost_proxy
echo "Protocol=ssh" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "HostName=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "ProxyLocalhost=1" >> ${OBJ}/.putty/sessions/localhost_proxy
PUTTYDIR=${OBJ}/.putty
export PUTTYDIR
REGRESS_INTEROP_PUTTY=yes
fi
# create a proxy version of the client config
(
cat $OBJ/ssh_config
echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
) > $OBJ/ssh_proxy
# check proxy config
${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken"
start_sshd ()
{
# start sshd
$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
$SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
trace "wait for sshd"
i=0;
while [ ! -f $PIDFILE -a $i -lt 10 ]; do
i=`expr $i + 1`
sleep $i
done
test -f $PIDFILE || fatal "no sshd running on port $PORT"
}
# source test body
. $SCRIPT
# kill sshd
cleanup
if [ $RESULT -eq 0 ]; then
verbose ok $tid
else
echo failed $tid
fi
exit $RESULT
diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc
index b509f4452500..428ef6836981 100644
--- a/regress/unittests/Makefile.inc
+++ b/regress/unittests/Makefile.inc
@@ -1,53 +1,86 @@
-# $OpenBSD: Makefile.inc,v 1.12 2017/12/21 00:41:22 djm Exp $
+# $OpenBSD: Makefile.inc,v 1.13 2018/10/17 23:28:05 djm Exp $
+
+REGRESS_FAIL_EARLY?= yes
.include <bsd.own.mk>
.include <bsd.obj.mk>
+# User-settable options
+UNITTEST_FAST?= no # Skip slow tests (e.g. less intensive fuzzing).
+UNITTEST_SLOW?= no # Include slower tests (e.g. more intensive fuzzing).
+UNITTEST_VERBOSE?= no # Verbose test output (inc. per-test names).
+
+MALLOC_OPTIONS?= CFGJRSUX
+TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS}
+
+# XXX detect from ssh binary?
+OPENSSL?= yes
+
+.if (${OPENSSL:L} == "yes")
+CFLAGS+= -DWITH_OPENSSL
+.endif
+
# enable warnings
WARNINGS=Yes
DEBUG=-g
CFLAGS+= -fstack-protector-all
CDIAGFLAGS= -Wall
CDIAGFLAGS+= -Wextra
CDIAGFLAGS+= -Werror
CDIAGFLAGS+= -Wchar-subscripts
CDIAGFLAGS+= -Wcomment
CDIAGFLAGS+= -Wformat
CDIAGFLAGS+= -Wformat-security
CDIAGFLAGS+= -Wimplicit
CDIAGFLAGS+= -Winline
CDIAGFLAGS+= -Wmissing-declarations
CDIAGFLAGS+= -Wmissing-prototypes
CDIAGFLAGS+= -Wparentheses
CDIAGFLAGS+= -Wpointer-arith
CDIAGFLAGS+= -Wreturn-type
CDIAGFLAGS+= -Wshadow
CDIAGFLAGS+= -Wsign-compare
CDIAGFLAGS+= -Wstrict-aliasing
CDIAGFLAGS+= -Wstrict-prototypes
CDIAGFLAGS+= -Wswitch
CDIAGFLAGS+= -Wtrigraphs
CDIAGFLAGS+= -Wuninitialized
CDIAGFLAGS+= -Wunused
CDIAGFLAGS+= -Wno-unused-parameter
.if ${COMPILER_VERSION:L} != "gcc3"
CDIAGFLAGS+= -Wold-style-definition
.endif
SSHREL=../../../../../usr.bin/ssh
CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL}
.if exists(${.CURDIR}/../test_helper/${__objdir})
LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper
DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a
.else
LDADD+=-L${.CURDIR}/../test_helper -ltest_helper
DPADD+=${.CURDIR}/../test_helper/libtest_helper.a
.endif
.PATH: ${.CURDIR}/${SSHREL}
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
+
+.if (${OPENSSL:L} == "yes")
LDADD+= -lcrypto
DPADD+= ${LIBCRYPTO}
+.endif
+
+UNITTEST_ARGS?=
+
+.if (${UNITTEST_VERBOSE:L} != "no")
+UNITTEST_ARGS+= -v
+.endif
+.if (${UNITTEST_FAST:L} != "no")
+UNITTEST_ARGS+= -f
+.elif (${UNITTEST_SLOW:L} != "no")
+UNITTEST_ARGS+= -F
+.endif
diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile
index 5c61307a325a..7b4c644e5fb1 100644
--- a/regress/unittests/kex/Makefile
+++ b/regress/unittests/kex/Makefile
@@ -1,29 +1,38 @@
-# $OpenBSD: Makefile,v 1.5 2017/12/21 00:41:22 djm Exp $
+# $OpenBSD: Makefile,v 1.6 2019/01/21 12:35:20 djm Exp $
PROG=test_kex
SRCS=tests.c test_kex.c
# From usr.bin/ssh
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c ssh-dss.c
SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
SRCS+=addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c
-SRCS+=kex.c kexc25519.c kexc25519c.c kexc25519s.c kexdh.c kexdhc.c kexdhs.c
-SRCS+=kexecdh.c kexecdhc.c kexecdhs.c kexgex.c kexgexc.c kexgexs.c
-SRCS+=dh.c compat.c
-SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
+SRCS+=compat.c ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c
-SRCS+=smult_curve25519_ref.c
+
+SRCS+= kex.c
+SRCS+= dh.c
+SRCS+= kexdh.c
+SRCS+= kexecdh.c
+SRCS+= kexgex.c
+SRCS+= kexgexc.c
+SRCS+= kexgexs.c
+SRCS+= kexc25519.c
+SRCS+= smult_curve25519_ref.c
+SRCS+= kexgen.c
+SRCS+= kexsntrup4591761x25519.c
+SRCS+= sntrup4591761.c
SRCS+=digest-openssl.c
#SRCS+=digest-libc.c
REGRESS_TARGETS=run-regress-${PROG}
run-regress-${PROG}: ${PROG}
env ${TEST_ENV} ./${PROG}
.include <bsd.regress.mk>
LDADD+=-lz
diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c
index 6e5999bb9edd..a860efc02947 100644
--- a/regress/unittests/kex/test_kex.c
+++ b/regress/unittests/kex/test_kex.c
@@ -1,202 +1,199 @@
-/* $OpenBSD: test_kex.c,v 1.2 2015/07/10 06:23:25 markus Exp $ */
+/* $OpenBSD: test_kex.c,v 1.4 2019/01/21 12:35:20 djm Exp $ */
/*
* Regress test KEX
*
* Placed in the public domain
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "../test_helper/test_helper.h"
#include "ssherr.h"
#include "ssh_api.h"
#include "sshbuf.h"
#include "packet.h"
#include "myproposal.h"
-struct ssh *active_state = NULL; /* XXX - needed for linking */
-
void kex_tests(void);
static int do_debug = 0;
static int
do_send_and_receive(struct ssh *from, struct ssh *to)
{
u_char type;
size_t len;
const u_char *buf;
int r;
for (;;) {
if ((r = ssh_packet_next(from, &type)) != 0) {
fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
return r;
}
if (type != 0)
return 0;
buf = ssh_output_ptr(from, &len);
if (do_debug)
printf("%zu", len);
if (len == 0)
return 0;
if ((r = ssh_output_consume(from, len)) != 0 ||
(r = ssh_input_append(to, buf, len)) != 0)
return r;
}
}
static void
run_kex(struct ssh *client, struct ssh *server)
{
int r = 0;
while (!server->kex->done || !client->kex->done) {
if (do_debug)
printf(" S:");
if ((r = do_send_and_receive(server, client)))
break;
if (do_debug)
printf(" C:");
if ((r = do_send_and_receive(client, server)))
break;
}
if (do_debug)
printf("done: %s\n", ssh_err(r));
ASSERT_INT_EQ(r, 0);
ASSERT_INT_EQ(server->kex->done, 1);
ASSERT_INT_EQ(client->kex->done, 1);
}
static void
do_kex_with_key(char *kex, int keytype, int bits)
{
struct ssh *client = NULL, *server = NULL, *server2 = NULL;
struct sshkey *private, *public;
struct sshbuf *state;
struct kex_params kex_params;
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
char *keyname = NULL;
TEST_START("sshkey_generate");
ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0);
TEST_DONE();
TEST_START("sshkey_from_private");
ASSERT_INT_EQ(sshkey_from_private(private, &public), 0);
TEST_DONE();
TEST_START("ssh_init");
memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
if (kex != NULL)
kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
keyname = strdup(sshkey_ssh_name(private));
ASSERT_PTR_NE(keyname, NULL);
kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
ASSERT_PTR_NE(client, NULL);
ASSERT_PTR_NE(server, NULL);
TEST_DONE();
TEST_START("ssh_add_hostkey");
ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0);
ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0);
TEST_DONE();
TEST_START("kex");
run_kex(client, server);
TEST_DONE();
TEST_START("rekeying client");
ASSERT_INT_EQ(kex_send_kexinit(client), 0);
run_kex(client, server);
TEST_DONE();
TEST_START("rekeying server");
ASSERT_INT_EQ(kex_send_kexinit(server), 0);
run_kex(client, server);
TEST_DONE();
TEST_START("ssh_packet_get_state");
state = sshbuf_new();
ASSERT_PTR_NE(state, NULL);
ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
ASSERT_INT_GE(sshbuf_len(state), 1);
TEST_DONE();
TEST_START("ssh_packet_set_state");
server2 = NULL;
ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
ASSERT_PTR_NE(server2, NULL);
ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0);
- kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */
ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
ASSERT_INT_EQ(sshbuf_len(state), 0);
sshbuf_free(state);
ASSERT_PTR_NE(server2->kex, NULL);
/* XXX we need to set the callbacks */
- server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+ server2->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
#ifdef OPENSSL_HAS_ECC
- server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
#endif
- server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
server2->kex->load_host_public_key = server->kex->load_host_public_key;
server2->kex->load_host_private_key = server->kex->load_host_private_key;
server2->kex->sign = server->kex->sign;
TEST_DONE();
TEST_START("rekeying server2");
ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
run_kex(client, server2);
ASSERT_INT_EQ(kex_send_kexinit(client), 0);
run_kex(client, server2);
TEST_DONE();
TEST_START("cleanup");
sshkey_free(private);
sshkey_free(public);
ssh_free(client);
ssh_free(server);
ssh_free(server2);
free(keyname);
TEST_DONE();
}
static void
do_kex(char *kex)
{
do_kex_with_key(kex, KEY_RSA, 2048);
do_kex_with_key(kex, KEY_DSA, 1024);
#ifdef OPENSSL_HAS_ECC
do_kex_with_key(kex, KEY_ECDSA, 256);
#endif
do_kex_with_key(kex, KEY_ED25519, 256);
}
void
kex_tests(void)
{
do_kex("curve25519-sha256@libssh.org");
#ifdef OPENSSL_HAS_ECC
do_kex("ecdh-sha2-nistp256");
do_kex("ecdh-sha2-nistp384");
do_kex("ecdh-sha2-nistp521");
#endif
do_kex("diffie-hellman-group-exchange-sha256");
do_kex("diffie-hellman-group-exchange-sha1");
do_kex("diffie-hellman-group14-sha1");
do_kex("diffie-hellman-group1-sha1");
}
diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile
index 81d4f27a6132..0e8e9fd1010e 100644
--- a/regress/unittests/sshbuf/Makefile
+++ b/regress/unittests/sshbuf/Makefile
@@ -1,22 +1,21 @@
-# $OpenBSD: Makefile,v 1.6 2017/12/21 00:41:22 djm Exp $
+# $OpenBSD: Makefile,v 1.7 2018/10/17 23:28:05 djm Exp $
.include <bsd.regress.mk>
PROG=test_sshbuf
SRCS=tests.c
SRCS+=test_sshbuf.c
SRCS+=test_sshbuf_getput_basic.c
SRCS+=test_sshbuf_getput_crypto.c
SRCS+=test_sshbuf_misc.c
SRCS+=test_sshbuf_fuzz.c
SRCS+=test_sshbuf_getput_fuzz.c
SRCS+=test_sshbuf_fixed.c
# From usr.bin/ssh
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=atomicio.c
run-regress-${PROG}: ${PROG}
- env ${TEST_ENV} ./${PROG}
-
+ env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS}
diff --git a/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_fuzz.c
index c52376b531a3..e236c82f96fc 100644
--- a/regress/unittests/sshbuf/test_sshbuf_fuzz.c
+++ b/regress/unittests/sshbuf/test_sshbuf_fuzz.c
@@ -1,127 +1,132 @@
-/* $OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
+/* $OpenBSD: test_sshbuf_fuzz.c,v 1.2 2018/10/17 23:28:05 djm Exp $ */
/*
* Regress test for sshbuf.h buffer API
*
* Placed in the public domain
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "../test_helper/test_helper.h"
#include "ssherr.h"
#include "sshbuf.h"
#define NUM_FUZZ_TESTS (1 << 18)
void sshbuf_fuzz_tests(void);
void
sshbuf_fuzz_tests(void)
{
struct sshbuf *p1;
u_char *dp;
- size_t sz, sz2, i;
+ size_t sz, sz2, i, ntests = NUM_FUZZ_TESTS;
u_int32_t r;
int ret;
+ if (test_is_fast())
+ ntests >>= 2;
+ if (test_is_slow())
+ ntests <<= 2;
+
/* NB. uses sshbuf internals */
TEST_START("fuzz alloc/dealloc");
p1 = sshbuf_new();
ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0);
ASSERT_PTR_NE(p1, NULL);
ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
for (i = 0; i < NUM_FUZZ_TESTS; i++) {
r = arc4random_uniform(10);
if (r == 0) {
/* 10% chance: small reserve */
r = arc4random_uniform(10);
fuzz_reserve:
sz = sshbuf_avail(p1);
sz2 = sshbuf_len(p1);
ret = sshbuf_reserve(p1, r, &dp);
if (ret < 0) {
ASSERT_PTR_EQ(dp, NULL);
ASSERT_SIZE_T_LT(sz, r);
ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
} else {
ASSERT_PTR_NE(dp, NULL);
ASSERT_SIZE_T_GE(sz, r);
ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r);
memset(dp, arc4random_uniform(255) + 1, r);
}
} else if (r < 3) {
/* 20% chance: big reserve */
r = arc4random_uniform(8 * 1024);
goto fuzz_reserve;
} else if (r == 3) {
/* 10% chance: small consume */
r = arc4random_uniform(10);
fuzz_consume:
sz = sshbuf_avail(p1);
sz2 = sshbuf_len(p1);
/* 50% change consume from end, otherwise start */
ret = ((arc4random() & 1) ?
sshbuf_consume : sshbuf_consume_end)(p1, r);
if (ret < 0) {
ASSERT_SIZE_T_LT(sz2, r);
ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
} else {
ASSERT_SIZE_T_GE(sz2, r);
ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r);
}
} else if (r < 8) {
/* 40% chance: big consume */
r = arc4random_uniform(2 * 1024);
goto fuzz_consume;
} else if (r == 8) {
/* 10% chance: reset max size */
r = arc4random_uniform(16 * 1024);
sz = sshbuf_max_size(p1);
if (sshbuf_set_max_size(p1, r) < 0)
ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
else
ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r);
} else {
if (arc4random_uniform(8192) == 0) {
/* tiny chance: new buffer */
ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
sshbuf_free(p1);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_set_max_size(p1,
16 * 1024), 0);
} else {
/* Almost 10%: giant reserve */
/* use arc4random_buf for r > 2^32 on 64 bit */
arc4random_buf(&r, sizeof(r));
while (r < SSHBUF_SIZE_MAX / 2) {
r <<= 1;
r |= arc4random() & 1;
}
goto fuzz_reserve;
}
}
ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024);
}
ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
sshbuf_free(p1);
TEST_DONE();
}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
index a68e1329e40b..5d39e63e170c 100644
--- a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
@@ -1,409 +1,278 @@
-/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
+/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.2 2019/01/21 12:29:35 djm Exp $ */
/*
* Regress test for sshbuf.h buffer API
*
* Placed in the public domain
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#ifdef OPENSSL_HAS_NISTP256
# include <openssl/ec.h>
#endif
#include "../test_helper/test_helper.h"
#include "ssherr.h"
#include "sshbuf.h"
void sshbuf_getput_crypto_tests(void);
void
sshbuf_getput_crypto_tests(void)
{
struct sshbuf *p1;
BIGNUM *bn, *bn2;
- /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */
const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10";
/* This one has MSB set to test bignum2 encoding negative-avoidance */
const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11";
u_char expbn1[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
};
u_char expbn2[] = {
0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
0x7f, 0xff, 0x11
};
#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
const u_char *d;
size_t s;
BIGNUM *bn_x, *bn_y;
int ec256_nid = NID_X9_62_prime256v1;
char *ec256_x = "0C828004839D0106AA59575216191357"
"34B451459DADB586677EF9DF55784999";
char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2"
"C8F9A35E42BDD047550F69D80EC23CD4";
u_char expec256[] = {
0x04,
0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06,
0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57,
0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86,
0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99,
0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b,
0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2,
0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47,
0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4
};
EC_KEY *eck;
EC_POINT *ecp;
#endif
int r;
#define MKBN(b, bnn) \
do { \
bnn = NULL; \
ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \
} while (0)
- TEST_START("sshbuf_put_bignum1");
- MKBN(hexbn1, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 2);
- ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn));
- ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn1, sizeof(expbn1));
- BN_free(bn);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_put_bignum1 limited");
- MKBN(hexbn1, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0);
- r = sshbuf_put_bignum1(p1, bn);
- ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
- BN_free(bn);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_put_bignum1 bn2");
- MKBN(hexbn2, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 2);
- ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn));
- ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn2, sizeof(expbn2));
- BN_free(bn);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_put_bignum1 bn2 limited");
- MKBN(hexbn2, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0);
- r = sshbuf_put_bignum1(p1, bn);
- ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
- BN_free(bn);
- sshbuf_free(p1);
- TEST_DONE();
-
TEST_START("sshbuf_put_bignum2");
MKBN(hexbn1, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4);
ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn));
ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1));
BN_free(bn);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_put_bignum2 limited");
MKBN(hexbn1, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0);
r = sshbuf_put_bignum2(p1, bn);
ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
BN_free(bn);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_put_bignum2 bn2");
MKBN(hexbn2, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */
ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1);
ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00);
ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2));
BN_free(bn);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_put_bignum2 bn2 limited");
MKBN(hexbn2, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0);
r = sshbuf_put_bignum2(p1, bn);
ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
BN_free(bn);
sshbuf_free(p1);
TEST_DONE();
- TEST_START("sshbuf_get_bignum1");
- MKBN(hexbn1, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
- ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1));
- ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
- bn2 = BN_new();
- ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0);
- ASSERT_BIGNUM_EQ(bn, bn2);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
- BN_free(bn);
- BN_free(bn2);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_get_bignum1 truncated");
- MKBN(hexbn1, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
- ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1);
- bn2 = BN_new();
- r = sshbuf_get_bignum1(p1, bn2);
- ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1);
- BN_free(bn);
- BN_free(bn2);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_get_bignum1 giant");
- MKBN(hexbn1, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xffff), 0);
- ASSERT_INT_EQ(sshbuf_reserve(p1, (0xffff + 7) / 8, NULL), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8));
- bn2 = BN_new();
- r = sshbuf_get_bignum1(p1, bn2);
- ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8));
- BN_free(bn);
- BN_free(bn2);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_get_bignum1 bn2");
- MKBN(hexbn2, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
- ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2));
- ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
- bn2 = BN_new();
- ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0);
- ASSERT_BIGNUM_EQ(bn, bn2);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
- BN_free(bn);
- BN_free(bn2);
- sshbuf_free(p1);
- TEST_DONE();
-
- TEST_START("sshbuf_get_bignum1 bn2 truncated");
- MKBN(hexbn2, bn);
- p1 = sshbuf_new();
- ASSERT_PTR_NE(p1, NULL);
- ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
- ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1);
- bn2 = BN_new();
- r = sshbuf_get_bignum1(p1, bn2);
- ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
- ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1);
- BN_free(bn);
- BN_free(bn2);
- sshbuf_free(p1);
- TEST_DONE();
-
TEST_START("sshbuf_get_bignum2");
MKBN(hexbn1, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1));
ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
- bn2 = BN_new();
- ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0);
+ bn2 = NULL;
+ ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn2), 0);
ASSERT_BIGNUM_EQ(bn, bn2);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
BN_free(bn);
BN_free(bn2);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_get_bignum2 truncated");
MKBN(hexbn1, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0);
- bn2 = BN_new();
- r = sshbuf_get_bignum2(p1, bn2);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3);
BN_free(bn);
BN_free(bn2);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_get_bignum2 giant");
MKBN(hexbn1, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0);
ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0);
- bn2 = BN_new();
- r = sshbuf_get_bignum2(p1, bn2);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4);
BN_free(bn);
BN_free(bn2);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_get_bignum2 bn2");
MKBN(hexbn2, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */
ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2));
ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
- bn2 = BN_new();
- ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0);
+ bn2 = NULL;
+ ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn2), 0);
ASSERT_BIGNUM_EQ(bn, bn2);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
BN_free(bn);
BN_free(bn2);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_get_bignum2 bn2 truncated");
MKBN(hexbn2, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0);
ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0);
- bn2 = BN_new();
- r = sshbuf_get_bignum2(p1, bn2);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1);
BN_free(bn);
BN_free(bn2);
sshbuf_free(p1);
TEST_DONE();
TEST_START("sshbuf_get_bignum2 bn2 negative");
MKBN(hexbn2, bn);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
- bn2 = BN_new();
- r = sshbuf_get_bignum2(p1, bn2);
+ bn2 = NULL;
+ r = sshbuf_get_bignum2(p1, &bn2);
ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4);
BN_free(bn);
BN_free(bn2);
sshbuf_free(p1);
TEST_DONE();
#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
TEST_START("sshbuf_put_ec");
eck = EC_KEY_new_by_curve_name(ec256_nid);
ASSERT_PTR_NE(eck, NULL);
ecp = EC_POINT_new(EC_KEY_get0_group(eck));
ASSERT_PTR_NE(ecp, NULL);
MKBN(ec256_x, bn_x);
MKBN(ec256_y, bn_y);
ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp(
EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1);
ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1);
BN_free(bn_x);
BN_free(bn_y);
EC_POINT_free(ecp);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0);
ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0);
ASSERT_SIZE_T_EQ(s, sizeof(expec256));
ASSERT_MEM_EQ(d, expec256, sizeof(expec256));
sshbuf_free(p1);
EC_KEY_free(eck);
TEST_DONE();
TEST_START("sshbuf_get_ec");
eck = EC_KEY_new_by_curve_name(ec256_nid);
ASSERT_PTR_NE(eck, NULL);
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4);
ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0);
bn_x = BN_new();
bn_y = BN_new();
ASSERT_PTR_NE(bn_x, NULL);
ASSERT_PTR_NE(bn_y, NULL);
ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp(
EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck),
bn_x, bn_y, NULL), 1);
MKBN(ec256_x, bn);
MKBN(ec256_y, bn2);
ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0);
ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0);
ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
sshbuf_free(p1);
EC_KEY_free(eck);
BN_free(bn_x);
BN_free(bn_y);
BN_free(bn);
BN_free(bn2);
TEST_DONE();
#endif
}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
index c6b5c29d176b..ca06bfb00ee0 100644
--- a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
@@ -1,130 +1,127 @@
-/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.2 2014/05/02 02:54:00 djm Exp $ */
+/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.4 2019/01/21 12:29:35 djm Exp $ */
/*
* Regress test for sshbuf.h buffer API
*
* Placed in the public domain
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#ifdef OPENSSL_HAS_NISTP256
# include <openssl/ec.h>
#endif
#include "../test_helper/test_helper.h"
#include "ssherr.h"
#include "sshbuf.h"
void sshbuf_getput_fuzz_tests(void);
static void
attempt_parse_blob(u_char *blob, size_t len)
{
struct sshbuf *p1;
BIGNUM *bn;
#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
EC_KEY *eck;
#endif
u_char *s;
size_t l;
u_int8_t u8;
u_int16_t u16;
u_int32_t u32;
u_int64_t u64;
p1 = sshbuf_new();
ASSERT_PTR_NE(p1, NULL);
ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0);
sshbuf_get_u8(p1, &u8);
sshbuf_get_u16(p1, &u16);
sshbuf_get_u32(p1, &u32);
sshbuf_get_u64(p1, &u64);
if (sshbuf_get_string(p1, &s, &l) == 0) {
bzero(s, l);
free(s);
}
- bn = BN_new();
- sshbuf_get_bignum1(p1, bn);
- BN_clear_free(bn);
- bn = BN_new();
- sshbuf_get_bignum2(p1, bn);
+ bn = NULL;
+ sshbuf_get_bignum2(p1, &bn);
BN_clear_free(bn);
#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
ASSERT_PTR_NE(eck, NULL);
sshbuf_get_eckey(p1, eck);
EC_KEY_free(eck);
#endif
sshbuf_free(p1);
}
static void
onerror(void *fuzz)
{
fprintf(stderr, "Failed during fuzz:\n");
fuzz_dump((struct fuzz *)fuzz);
}
void
sshbuf_getput_fuzz_tests(void)
{
u_char blob[] = {
/* u8 */
0xd0,
/* u16 */
0xc0, 0xde,
/* u32 */
0xfa, 0xce, 0xde, 0xad,
/* u64 */
0xfe, 0xed, 0xac, 0x1d, 0x1f, 0x1c, 0xbe, 0xef,
/* string */
0x00, 0x00, 0x00, 0x09,
'O', ' ', 'G', 'o', 'r', 'g', 'o', 'n', '!',
- /* bignum1 */
- 0x79,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
/* bignum2 */
0x00, 0x00, 0x00, 0x14,
0x00,
0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
0x7f, 0xff, 0x11,
/* EC point (NIST-256 curve) */
0x00, 0x00, 0x00, 0x41,
0x04,
0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06,
0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57,
0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86,
0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99,
0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b,
0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2,
0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47,
0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4,
};
struct fuzz *fuzz;
+ u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP |
+ FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
+
+ if (test_is_fast())
+ fuzzers &= ~(FUZZ_2_BYTE_FLIP|FUZZ_2_BIT_FLIP);
TEST_START("fuzz blob parsing");
- fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP |
- FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
- FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, blob, sizeof(blob));
+ fuzz = fuzz_begin(fuzzers, blob, sizeof(blob));
TEST_ONERROR(onerror, fuzz);
for(; !fuzz_done(fuzz); fuzz_next(fuzz))
attempt_parse_blob(blob, sizeof(blob));
fuzz_cleanup(fuzz);
TEST_DONE();
TEST_ONERROR(NULL, NULL);
}
diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile
index 1c940bec640b..aa731df1c2d4 100644
--- a/regress/unittests/sshkey/Makefile
+++ b/regress/unittests/sshkey/Makefile
@@ -1,24 +1,24 @@
-# $OpenBSD: Makefile,v 1.5 2017/12/21 00:41:22 djm Exp $
+# $OpenBSD: Makefile,v 1.6 2018/10/17 23:28:05 djm Exp $
PROG=test_sshkey
SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c
# From usr.bin/ssh
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c ssh-dss.c
SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
SRCS+=addrmatch.c bitmap.c
SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c
SRCS+=digest-openssl.c
#SRCS+=digest-libc.c
REGRESS_TARGETS=run-regress-${PROG}
run-regress-${PROG}: ${PROG}
- env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
+ env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata
.include <bsd.regress.mk>
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c
index d3b0c92b47a0..5953de595852 100644
--- a/regress/unittests/sshkey/test_fuzz.c
+++ b/regress/unittests/sshkey/test_fuzz.c
@@ -1,360 +1,383 @@
-/* $OpenBSD: test_fuzz.c,v 1.8 2017/12/21 00:41:22 djm Exp $ */
+/* $OpenBSD: test_fuzz.c,v 1.9 2018/10/17 23:28:05 djm Exp $ */
/*
* Fuzz tests for key parsing
*
* Placed in the public domain
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/objects.h>
#ifdef OPENSSL_HAS_NISTP256
# include <openssl/ec.h>
#endif
#include "../test_helper/test_helper.h"
#include "ssherr.h"
#include "authfile.h"
#include "sshkey.h"
#include "sshbuf.h"
#include "common.h"
void sshkey_fuzz_tests(void);
static void
onerror(void *fuzz)
{
fprintf(stderr, "Failed during fuzz:\n");
fuzz_dump((struct fuzz *)fuzz);
}
static void
public_fuzz(struct sshkey *k)
{
struct sshkey *k1;
struct sshbuf *buf;
struct fuzz *fuzz;
+ u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
+ if (test_is_fast())
+ fuzzers &= ~FUZZ_1_BIT_FLIP;
+ if (test_is_slow())
+ fuzzers |= FUZZ_2_BIT_FLIP | FUZZ_2_BYTE_FLIP;
ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
ASSERT_INT_EQ(sshkey_putb(k, buf), 0);
- /* XXX need a way to run the tests in "slow, but complete" mode */
- fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */
- FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */
- FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
- sshbuf_mutable_ptr(buf), sshbuf_len(buf));
+ fuzz = fuzz_begin(fuzzers, sshbuf_mutable_ptr(buf), sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf),
&k1), 0);
sshkey_free(k1);
sshbuf_free(buf);
TEST_ONERROR(onerror, fuzz);
for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0)
sshkey_free(k1);
}
fuzz_cleanup(fuzz);
}
static void
sig_fuzz(struct sshkey *k, const char *sig_alg)
{
struct fuzz *fuzz;
u_char *sig, c[] = "some junk to be signed";
size_t l;
+ u_int fuzzers = FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
+ FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END;
+
+ if (test_is_fast())
+ fuzzers &= ~FUZZ_2_BYTE_FLIP;
+ if (test_is_slow())
+ fuzzers |= FUZZ_2_BIT_FLIP;
ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), sig_alg, 0), 0);
ASSERT_SIZE_T_GT(l, 0);
- fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* too slow FUZZ_2_BIT_FLIP | */
- FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
- FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sig, l);
+ fuzz = fuzz_begin(fuzzers, sig, l);
ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), NULL, 0), 0);
free(sig);
TEST_ONERROR(onerror, fuzz);
for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
/* Ensure 1-bit difference at least */
if (fuzz_matches_original(fuzz))
continue;
ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
c, sizeof(c), NULL, 0), 0);
}
fuzz_cleanup(fuzz);
}
+#define NUM_FAST_BASE64_TESTS 1024
+
void
sshkey_fuzz_tests(void)
{
struct sshkey *k1;
struct sshbuf *buf, *fuzzed;
struct fuzz *fuzz;
- int r;
+ int r, i;
TEST_START("fuzz RSA private");
buf = load_file("rsa_1");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
TEST_START("fuzz RSA new-format private");
buf = load_file("rsa_n");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
TEST_START("fuzz DSA private");
buf = load_file("dsa_1");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
TEST_START("fuzz DSA new-format private");
buf = load_file("dsa_n");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
#ifdef OPENSSL_HAS_ECC
TEST_START("fuzz ECDSA private");
buf = load_file("ecdsa_1");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
TEST_START("fuzz ECDSA new-format private");
buf = load_file("ecdsa_n");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
#endif
TEST_START("fuzz Ed25519 private");
buf = load_file("ed25519_1");
fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
sshbuf_len(buf));
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshkey_free(k1);
sshbuf_free(buf);
ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
TEST_ONERROR(onerror, fuzz);
- for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
+ for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) {
r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
ASSERT_INT_EQ(r, 0);
if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0)
sshkey_free(k1);
sshbuf_reset(fuzzed);
+ if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS)
+ break;
}
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
TEST_START("fuzz RSA public");
buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz RSA cert");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz DSA public");
buf = load_file("dsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz DSA cert");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
#ifdef OPENSSL_HAS_ECC
TEST_START("fuzz ECDSA public");
buf = load_file("ecdsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz ECDSA cert");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
#endif
TEST_START("fuzz Ed25519 public");
buf = load_file("ed25519_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz Ed25519 cert");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
public_fuzz(k1);
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz RSA sig");
buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, "ssh-rsa");
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz RSA SHA256 sig");
buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, "rsa-sha2-256");
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz RSA SHA512 sig");
buf = load_file("rsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, "rsa-sha2-512");
sshkey_free(k1);
TEST_DONE();
TEST_START("fuzz DSA sig");
buf = load_file("dsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, NULL);
sshkey_free(k1);
TEST_DONE();
#ifdef OPENSSL_HAS_ECC
TEST_START("fuzz ECDSA sig");
buf = load_file("ecdsa_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, NULL);
sshkey_free(k1);
TEST_DONE();
#endif
TEST_START("fuzz Ed25519 sig");
buf = load_file("ed25519_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
sshbuf_free(buf);
sig_fuzz(k1, NULL);
sshkey_free(k1);
TEST_DONE();
/* XXX fuzz decoded new-format blobs too */
}
diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c
index 13f265cdb91b..78aa9223d42b 100644
--- a/regress/unittests/sshkey/tests.c
+++ b/regress/unittests/sshkey/tests.c
@@ -1,27 +1,22 @@
/* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
/*
* Regress test for sshbuf.h buffer API
*
* Placed in the public domain
*/
#include "includes.h"
-#include <openssl/evp.h>
-
#include "../test_helper/test_helper.h"
void sshkey_tests(void);
void sshkey_file_tests(void);
void sshkey_fuzz_tests(void);
void
tests(void)
{
- OpenSSL_add_all_algorithms();
- ERR_load_CRYPTO_strings();
-
sshkey_tests();
sshkey_file_tests();
sshkey_fuzz_tests();
}
diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c
index 4cc70852c044..e7a47b265a8d 100644
--- a/regress/unittests/test_helper/test_helper.c
+++ b/regress/unittests/test_helper/test_helper.c
@@ -1,548 +1,573 @@
-/* $OpenBSD: test_helper.c,v 1.8 2018/02/08 08:46:20 djm Exp $ */
+/* $OpenBSD: test_helper.c,v 1.11 2018/11/23 02:53:57 dtucker Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Utility functions/framework for regress tests */
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <openssl/bn.h>
+#include <openssl/err.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
# include <vis.h>
#endif
+#include "entropy.h"
#include "test_helper.h"
#include "atomicio.h"
#define TEST_CHECK_INT(r, pred) do { \
switch (pred) { \
case TEST_EQ: \
if (r == 0) \
return; \
break; \
case TEST_NE: \
if (r != 0) \
return; \
break; \
case TEST_LT: \
if (r < 0) \
return; \
break; \
case TEST_LE: \
if (r <= 0) \
return; \
break; \
case TEST_GT: \
if (r > 0) \
return; \
break; \
case TEST_GE: \
if (r >= 0) \
return; \
break; \
default: \
abort(); \
} \
} while (0)
#define TEST_CHECK(x1, x2, pred) do { \
switch (pred) { \
case TEST_EQ: \
if (x1 == x2) \
return; \
break; \
case TEST_NE: \
if (x1 != x2) \
return; \
break; \
case TEST_LT: \
if (x1 < x2) \
return; \
break; \
case TEST_LE: \
if (x1 <= x2) \
return; \
break; \
case TEST_GT: \
if (x1 > x2) \
return; \
break; \
case TEST_GE: \
if (x1 >= x2) \
return; \
break; \
default: \
abort(); \
} \
} while (0)
extern char *__progname;
static int verbose_mode = 0;
static int quiet_mode = 0;
static char *active_test_name = NULL;
static u_int test_number = 0;
static test_onerror_func_t *test_onerror = NULL;
static void *onerror_ctx = NULL;
static const char *data_dir = NULL;
static char subtest_info[512];
+static int fast = 0;
+static int slow = 0;
int
main(int argc, char **argv)
{
int ch;
+ seed_rng();
+ ERR_load_CRYPTO_strings();
+
/* Handle systems without __progname */
if (__progname == NULL) {
__progname = strrchr(argv[0], '/');
if (__progname == NULL || __progname[1] == '\0')
__progname = argv[0];
else
__progname++;
if ((__progname = strdup(__progname)) == NULL) {
fprintf(stderr, "strdup failed\n");
exit(1);
}
}
- while ((ch = getopt(argc, argv, "vqd:")) != -1) {
+ while ((ch = getopt(argc, argv, "Ffvqd:")) != -1) {
switch (ch) {
+ case 'F':
+ slow = 1;
+ break;
+ case 'f':
+ fast = 1;
+ break;
case 'd':
data_dir = optarg;
break;
case 'q':
verbose_mode = 0;
quiet_mode = 1;
break;
case 'v':
verbose_mode = 1;
quiet_mode = 0;
break;
default:
fprintf(stderr, "Unrecognised command line option\n");
fprintf(stderr, "Usage: %s [-v]\n", __progname);
exit(1);
}
}
setvbuf(stdout, NULL, _IONBF, 0);
if (!quiet_mode)
printf("%s: ", __progname);
if (verbose_mode)
printf("\n");
tests();
if (!quiet_mode)
printf(" %u tests ok\n", test_number);
return 0;
}
int
-test_is_verbose()
+test_is_verbose(void)
{
return verbose_mode;
}
int
-test_is_quiet()
+test_is_quiet(void)
{
return quiet_mode;
}
+int
+test_is_fast(void)
+{
+ return fast;
+}
+
+int
+test_is_slow(void)
+{
+ return slow;
+}
+
const char *
test_data_file(const char *name)
{
static char ret[PATH_MAX];
if (data_dir != NULL)
snprintf(ret, sizeof(ret), "%s/%s", data_dir, name);
else
strlcpy(ret, name, sizeof(ret));
if (access(ret, F_OK) != 0) {
fprintf(stderr, "Cannot access data file %s: %s\n",
ret, strerror(errno));
exit(1);
}
return ret;
}
void
test_info(char *s, size_t len)
{
snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number,
active_test_name == NULL ? "<none>" : active_test_name,
*subtest_info != '\0' ? " - " : "", subtest_info);
}
static void
siginfo(int unused __attribute__((__unused__)))
{
char buf[256];
test_info(buf, sizeof(buf));
atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
}
void
test_start(const char *n)
{
assert(active_test_name == NULL);
assert((active_test_name = strdup(n)) != NULL);
*subtest_info = '\0';
if (verbose_mode)
printf("test %u - \"%s\": ", test_number, active_test_name);
test_number++;
#ifdef SIGINFO
signal(SIGINFO, siginfo);
#endif
signal(SIGUSR1, siginfo);
}
void
set_onerror_func(test_onerror_func_t *f, void *ctx)
{
test_onerror = f;
onerror_ctx = ctx;
}
void
test_done(void)
{
*subtest_info = '\0';
assert(active_test_name != NULL);
free(active_test_name);
active_test_name = NULL;
if (verbose_mode)
printf("OK\n");
else if (!quiet_mode) {
printf(".");
fflush(stdout);
}
}
void
test_subtest_info(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap);
va_end(ap);
}
void
ssl_err_check(const char *file, int line)
{
long openssl_error = ERR_get_error();
if (openssl_error == 0)
return;
fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s",
file, line, ERR_error_string(openssl_error, NULL));
abort();
}
static const char *
pred_name(enum test_predicate p)
{
switch (p) {
case TEST_EQ:
return "EQ";
case TEST_NE:
return "NE";
case TEST_LT:
return "LT";
case TEST_LE:
return "LE";
case TEST_GT:
return "GT";
case TEST_GE:
return "GE";
default:
return "UNKNOWN";
}
}
static void
test_die(void)
{
if (test_onerror != NULL)
test_onerror(onerror_ctx);
abort();
}
static void
test_header(const char *file, int line, const char *a1, const char *a2,
const char *name, enum test_predicate pred)
{
fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n",
file, line, test_number, active_test_name,
*subtest_info != '\0' ? " - " : "", subtest_info);
fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
name, pred_name(pred), a1,
a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
}
void
assert_bignum(const char *file, int line, const char *a1, const char *a2,
const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred)
{
int r = BN_cmp(aa1, aa2);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, a2, "BIGNUM", pred);
fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1));
fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2));
test_die();
}
void
assert_string(const char *file, int line, const char *a1, const char *a2,
const char *aa1, const char *aa2, enum test_predicate pred)
{
int r;
/* Verify pointers are not NULL */
assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
r = strcmp(aa1, aa2);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, a2, "STRING", pred);
fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2));
test_die();
}
static char *
tohex(const void *_s, size_t l)
{
u_int8_t *s = (u_int8_t *)_s;
size_t i, j;
const char *hex = "0123456789abcdef";
char *r = malloc((l * 2) + 1);
assert(r != NULL);
for (i = j = 0; i < l; i++) {
r[j++] = hex[(s[i] >> 4) & 0xf];
r[j++] = hex[s[i] & 0xf];
}
r[j] = '\0';
return r;
}
void
assert_mem(const char *file, int line, const char *a1, const char *a2,
const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
{
int r;
if (l == 0)
return;
/* If length is >0, then verify pointers are not NULL */
assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
r = memcmp(aa1, aa2, l);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, a2, "STRING", pred);
fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l);
fprintf(stderr, "%12s = %s (len %zu)\n", a2, tohex(aa2, MIN(l, 256)), l);
test_die();
}
static int
memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where)
{
size_t i;
for (i = 0; i < l; i++) {
if (s[i] != v) {
*where = i;
return 1;
}
}
return 0;
}
void
assert_mem_filled(const char *file, int line, const char *a1,
const void *aa1, u_char v, size_t l, enum test_predicate pred)
{
size_t where = -1;
int r;
char tmp[64];
if (l == 0)
return;
/* If length is >0, then verify the pointer is not NULL */
assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
r = memvalcmp(aa1, v, l, &where);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, NULL, "MEM_ZERO", pred);
fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
tohex(aa1, MIN(l, 20)), l > 20 ? "..." : "", l);
snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where);
fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp,
((u_char *)aa1)[where], v);
test_die();
}
void
assert_int(const char *file, int line, const char *a1, const char *a2,
int aa1, int aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "INT", pred);
fprintf(stderr, "%12s = %d\n", a1, aa1);
fprintf(stderr, "%12s = %d\n", a2, aa2);
test_die();
}
void
assert_size_t(const char *file, int line, const char *a1, const char *a2,
size_t aa1, size_t aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "SIZE_T", pred);
fprintf(stderr, "%12s = %zu\n", a1, aa1);
fprintf(stderr, "%12s = %zu\n", a2, aa2);
test_die();
}
void
assert_u_int(const char *file, int line, const char *a1, const char *a2,
u_int aa1, u_int aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "U_INT", pred);
fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1);
fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2);
test_die();
}
void
assert_long(const char *file, int line, const char *a1, const char *a2,
long aa1, long aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "LONG", pred);
fprintf(stderr, "%12s = %ld / 0x%lx\n", a1, aa1, aa1);
fprintf(stderr, "%12s = %ld / 0x%lx\n", a2, aa2, aa2);
test_die();
}
void
assert_long_long(const char *file, int line, const char *a1, const char *a2,
long long aa1, long long aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "LONG LONG", pred);
fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1);
fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2);
test_die();
}
void
assert_char(const char *file, int line, const char *a1, const char *a2,
char aa1, char aa2, enum test_predicate pred)
{
char buf[8];
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "CHAR", pred);
fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1);
fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2);
test_die();
}
void
assert_u8(const char *file, int line, const char *a1, const char *a2,
u_int8_t aa1, u_int8_t aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "U8", pred);
fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1);
fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2);
test_die();
}
void
assert_u16(const char *file, int line, const char *a1, const char *a2,
u_int16_t aa1, u_int16_t aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "U16", pred);
fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1);
fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2);
test_die();
}
void
assert_u32(const char *file, int line, const char *a1, const char *a2,
u_int32_t aa1, u_int32_t aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "U32", pred);
fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1);
fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2);
test_die();
}
void
assert_u64(const char *file, int line, const char *a1, const char *a2,
u_int64_t aa1, u_int64_t aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "U64", pred);
fprintf(stderr, "%12s = 0x%016llx %llu\n", a1,
(unsigned long long)aa1, (unsigned long long)aa1);
fprintf(stderr, "%12s = 0x%016llx %llu\n", a2,
(unsigned long long)aa2, (unsigned long long)aa2);
test_die();
}
void
assert_ptr(const char *file, int line, const char *a1, const char *a2,
const void *aa1, const void *aa2, enum test_predicate pred)
{
TEST_CHECK(aa1, aa2, pred);
test_header(file, line, a1, a2, "PTR", pred);
fprintf(stderr, "%12s = %p\n", a1, aa1);
fprintf(stderr, "%12s = %p\n", a2, aa2);
test_die();
}
diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h
index 6da0066e907a..1f893c8dd22e 100644
--- a/regress/unittests/test_helper/test_helper.h
+++ b/regress/unittests/test_helper/test_helper.h
@@ -1,320 +1,322 @@
-/* $OpenBSD: test_helper.h,v 1.8 2018/02/08 08:46:20 djm Exp $ */
+/* $OpenBSD: test_helper.h,v 1.9 2018/10/17 23:28:05 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Utility functions/framework for regress tests */
#ifndef _TEST_HELPER_H
#define _TEST_HELPER_H
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <openssl/bn.h>
#include <openssl/err.h>
enum test_predicate {
TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE
};
typedef void (test_onerror_func_t)(void *);
/* Supplied by test suite */
void tests(void);
const char *test_data_file(const char *name);
void test_start(const char *n);
void test_info(char *s, size_t len);
void set_onerror_func(test_onerror_func_t *f, void *ctx);
void test_done(void);
int test_is_verbose(void);
int test_is_quiet(void);
+int test_is_fast(void);
+int test_is_slow(void);
void test_subtest_info(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
void ssl_err_check(const char *file, int line);
void assert_bignum(const char *file, int line,
const char *a1, const char *a2,
const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred);
void assert_string(const char *file, int line,
const char *a1, const char *a2,
const char *aa1, const char *aa2, enum test_predicate pred);
void assert_mem(const char *file, int line,
const char *a1, const char *a2,
const void *aa1, const void *aa2, size_t l, enum test_predicate pred);
void assert_mem_filled(const char *file, int line,
const char *a1,
const void *aa1, u_char v, size_t l, enum test_predicate pred);
void assert_int(const char *file, int line,
const char *a1, const char *a2,
int aa1, int aa2, enum test_predicate pred);
void assert_size_t(const char *file, int line,
const char *a1, const char *a2,
size_t aa1, size_t aa2, enum test_predicate pred);
void assert_u_int(const char *file, int line,
const char *a1, const char *a2,
u_int aa1, u_int aa2, enum test_predicate pred);
void assert_long(const char *file, int line,
const char *a1, const char *a2,
long aa1, long aa2, enum test_predicate pred);
void assert_long_long(const char *file, int line,
const char *a1, const char *a2,
long long aa1, long long aa2, enum test_predicate pred);
void assert_char(const char *file, int line,
const char *a1, const char *a2,
char aa1, char aa2, enum test_predicate pred);
void assert_ptr(const char *file, int line,
const char *a1, const char *a2,
const void *aa1, const void *aa2, enum test_predicate pred);
void assert_u8(const char *file, int line,
const char *a1, const char *a2,
u_int8_t aa1, u_int8_t aa2, enum test_predicate pred);
void assert_u16(const char *file, int line,
const char *a1, const char *a2,
u_int16_t aa1, u_int16_t aa2, enum test_predicate pred);
void assert_u32(const char *file, int line,
const char *a1, const char *a2,
u_int32_t aa1, u_int32_t aa2, enum test_predicate pred);
void assert_u64(const char *file, int line,
const char *a1, const char *a2,
u_int64_t aa1, u_int64_t aa2, enum test_predicate pred);
#define TEST_START(n) test_start(n)
#define TEST_DONE() test_done()
#define TEST_ONERROR(f, c) set_onerror_func(f, c)
#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__)
#define ASSERT_BIGNUM_EQ(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_STRING_EQ(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_MEM_EQ(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ)
#define ASSERT_MEM_FILLED_EQ(a1, c, l) \
assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ)
#define ASSERT_MEM_ZERO_EQ(a1, l) \
assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ)
#define ASSERT_INT_EQ(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_SIZE_T_EQ(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U_INT_EQ(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_LONG_EQ(a1, a2) \
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_LONG_LONG_EQ(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_CHAR_EQ(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_PTR_EQ(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U8_EQ(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U16_EQ(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U32_EQ(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_U64_EQ(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
#define ASSERT_BIGNUM_NE(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_STRING_NE(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_MEM_NE(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE)
#define ASSERT_MEM_ZERO_NE(a1, l) \
assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE)
#define ASSERT_INT_NE(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_SIZE_T_NE(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U_INT_NE(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_LONG_NE(a1, a2) \
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_LONG_LONG_NE(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_CHAR_NE(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_PTR_NE(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U8_NE(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U16_NE(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U32_NE(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_U64_NE(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
#define ASSERT_BIGNUM_LT(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_STRING_LT(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_MEM_LT(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT)
#define ASSERT_INT_LT(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_SIZE_T_LT(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U_INT_LT(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_LONG_LT(a1, a2) \
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_LONG_LONG_LT(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_CHAR_LT(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_PTR_LT(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U8_LT(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U16_LT(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U32_LT(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_U64_LT(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
#define ASSERT_BIGNUM_LE(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_STRING_LE(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_MEM_LE(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE)
#define ASSERT_INT_LE(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_SIZE_T_LE(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U_INT_LE(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_LONG_LE(a1, a2) \
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_LONG_LONG_LE(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_CHAR_LE(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_PTR_LE(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U8_LE(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U16_LE(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U32_LE(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_U64_LE(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
#define ASSERT_BIGNUM_GT(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_STRING_GT(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_MEM_GT(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT)
#define ASSERT_INT_GT(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_SIZE_T_GT(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U_INT_GT(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_LONG_GT(a1, a2) \
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_LONG_LONG_GT(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_CHAR_GT(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_PTR_GT(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U8_GT(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U16_GT(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U32_GT(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_U64_GT(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
#define ASSERT_BIGNUM_GE(a1, a2) \
assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_STRING_GE(a1, a2) \
assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_MEM_GE(a1, a2, l) \
assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE)
#define ASSERT_INT_GE(a1, a2) \
assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_SIZE_T_GE(a1, a2) \
assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U_INT_GE(a1, a2) \
assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_LONG_GE(a1, a2) \
assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_LONG_LONG_GE(a1, a2) \
assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_CHAR_GE(a1, a2) \
assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_PTR_GE(a1, a2) \
assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U8_GE(a1, a2) \
assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U16_GE(a1, a2) \
assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U32_GE(a1, a2) \
assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
#define ASSERT_U64_GE(a1, a2) \
assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
/* Fuzzing support */
struct fuzz;
#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */
#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */
#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */
#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */
#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */
#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */
#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */
#define FUZZ_MAX FUZZ_BASE64
/* Start fuzzing a blob of data with selected strategies (bitmask) */
struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l);
/* Free a fuzz context */
void fuzz_cleanup(struct fuzz *fuzz);
/* Prepare the next fuzz case in the series */
void fuzz_next(struct fuzz *fuzz);
/*
* Check whether this fuzz case is identical to the original
* This is slow, but useful if the caller needs to ensure that all tests
* generated change the input (e.g. when fuzzing signatures).
*/
int fuzz_matches_original(struct fuzz *fuzz);
/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */
int fuzz_done(struct fuzz *fuzz);
/* Return the length and a pointer to the current fuzzed case */
size_t fuzz_len(struct fuzz *fuzz);
u_char *fuzz_ptr(struct fuzz *fuzz);
/* Dump the current fuzz case to stderr */
void fuzz_dump(struct fuzz *fuzz);
#endif /* _TEST_HELPER_H */
diff --git a/scp.0 b/scp.0
index 03157e8b7240..045f1183d8b4 100644
--- a/scp.0
+++ b/scp.0
@@ -1,163 +1,182 @@
SCP(1) General Commands Manual SCP(1)
NAME
scp M-bM-^@M-^S secure copy (remote file copy program)
SYNOPSIS
- scp [-346BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
- [-l limit] [-o ssh_option] [-P port] [-S program] source ... target
+ scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]
+ [-J destination] [-l limit] [-o ssh_option] [-P port] [-S program]
+ source ... target
DESCRIPTION
scp copies files between hosts on a network. It uses ssh(1) for data
transfer, and uses the same authentication and provides the same security
as ssh(1). scp will ask for passwords or passphrases if they are needed
for authentication.
The source and target may be specified as a local pathname, a remote host
with optional path in the form [user@]host:[path], or a URI in the form
scp://[user@]host[:port][/path]. Local file names can be made explicit
using absolute or relative pathnames to avoid scp treating file names
containing M-bM-^@M-^X:M-bM-^@M-^Y as host specifiers.
When copying between two remote hosts, if the URI format is used, a port
may only be specified on the target if the -3 option is used.
The options are as follows:
-3 Copies between two remote hosts are transferred through the local
host. Without this option the data is copied directly between
the two remote hosts. Note that this option disables the
progress meter.
-4 Forces scp to use IPv4 addresses only.
-6 Forces scp to use IPv6 addresses only.
-B Selects batch mode (prevents asking for passwords or
passphrases).
-C Compression enable. Passes the -C flag to ssh(1) to enable
compression.
-c cipher
Selects the cipher to use for encrypting the data transfer. This
option is directly passed to ssh(1).
-F ssh_config
Specifies an alternative per-user configuration file for ssh.
This option is directly passed to ssh(1).
-i identity_file
Selects the file from which the identity (private key) for public
key authentication is read. This option is directly passed to
ssh(1).
+ -J destination
+ Connect to the target host by first making an scp connection to
+ the jump host described by destination and then establishing a
+ TCP forwarding to the ultimate destination from there. Multiple
+ jump hops may be specified separated by comma characters. This
+ is a shortcut to specify a ProxyJump configuration directive.
+ This option is directly passed to ssh(1).
+
-l limit
Limits the used bandwidth, specified in Kbit/s.
-o ssh_option
Can be used to pass options to ssh in the format used in
ssh_config(5). This is useful for specifying options for which
there is no separate scp command-line flag. For full details of
the options listed below, and their possible values, see
ssh_config(5).
AddressFamily
BatchMode
BindAddress
BindInterface
CanonicalDomains
CanonicalizeFallbackLocal
CanonicalizeHostname
CanonicalizeMaxDots
CanonicalizePermittedCNAMEs
CASignatureAlgorithms
CertificateFile
ChallengeResponseAuthentication
CheckHostIP
Ciphers
Compression
ConnectionAttempts
ConnectTimeout
ControlMaster
ControlPath
ControlPersist
GlobalKnownHostsFile
GSSAPIAuthentication
GSSAPIDelegateCredentials
HashKnownHosts
Host
HostbasedAuthentication
HostbasedKeyTypes
HostKeyAlgorithms
HostKeyAlias
HostName
IdentitiesOnly
IdentityAgent
IdentityFile
IPQoS
KbdInteractiveAuthentication
KbdInteractiveDevices
KexAlgorithms
LogLevel
MACs
NoHostAuthenticationForLocalhost
NumberOfPasswordPrompts
PasswordAuthentication
PKCS11Provider
Port
PreferredAuthentications
ProxyCommand
ProxyJump
PubkeyAcceptedKeyTypes
PubkeyAuthentication
RekeyLimit
SendEnv
ServerAliveInterval
ServerAliveCountMax
SetEnv
StrictHostKeyChecking
TCPKeepAlive
UpdateHostKeys
User
UserKnownHostsFile
VerifyHostKeyDNS
-P port
Specifies the port to connect to on the remote host. Note that
this option is written with a capital M-bM-^@M-^XPM-bM-^@M-^Y, because -p is already
reserved for preserving the times and modes of the file.
-p Preserves modification times, access times, and modes from the
original file.
-q Quiet mode: disables the progress meter as well as warning and
diagnostic messages from ssh(1).
-r Recursively copy entire directories. Note that scp follows
symbolic links encountered in the tree traversal.
-S program
Name of program to use for the encrypted connection. The program
must understand ssh(1) options.
+ -T Disable strict filename checking. By default when copying files
+ from a remote host to a local directory scp checks that the
+ received filenames match those requested on the command-line to
+ prevent the remote end from sending unexpected or unwanted files.
+ Because of differences in how various operating systems and
+ shells interpret filename wildcards, these checks may cause
+ wanted files to be rejected. This option disables these checks
+ at the expense of fully trusting that the server will not send
+ unexpected filenames.
+
-v Verbose mode. Causes scp and ssh(1) to print debugging messages
about their progress. This is helpful in debugging connection,
authentication, and configuration problems.
EXIT STATUS
The scp utility exitsM-BM- 0 on success, andM-BM- >0 if an error occurs.
SEE ALSO
sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh_config(5),
sshd(8)
HISTORY
scp is based on the rcp program in BSD source code from the Regents of
the University of California.
AUTHORS
Timo Rinne <tri@iki.fi>
Tatu Ylonen <ylo@cs.hut.fi>
-OpenBSD 6.4 September 20, 2018 OpenBSD 6.4
+OpenBSD 6.5 January 26, 2019 OpenBSD 6.5
diff --git a/scp.1 b/scp.1
index 397e7709195a..a2833dab041f 100644
--- a/scp.1
+++ b/scp.1
@@ -1,248 +1,262 @@
.\"
.\" scp.1
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\"
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" Created: Sun May 7 00:14:37 1995 ylo
.\"
-.\" $OpenBSD: scp.1,v 1.81 2018/09/20 06:58:48 jmc Exp $
+.\" $OpenBSD: scp.1,v 1.85 2019/01/26 22:41:28 djm Exp $
.\"
-.Dd $Mdocdate: September 20 2018 $
+.Dd $Mdocdate: January 26 2019 $
.Dt SCP 1
.Os
.Sh NAME
.Nm scp
.Nd secure copy (remote file copy program)
.Sh SYNOPSIS
.Nm scp
.Op Fl 346BCpqrTv
.Op Fl c Ar cipher
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
+.Op Fl J Ar destination
.Op Fl l Ar limit
.Op Fl o Ar ssh_option
.Op Fl P Ar port
.Op Fl S Ar program
.Ar source ... target
.Sh DESCRIPTION
.Nm
copies files between hosts on a network.
It uses
.Xr ssh 1
for data transfer, and uses the same authentication and provides the
same security as
.Xr ssh 1 .
.Nm
will ask for passwords or passphrases if they are needed for
authentication.
.Pp
The
.Ar source
and
.Ar target
may be specified as a local pathname, a remote host with optional path
in the form
.Sm off
.Oo user @ Oc host : Op path ,
.Sm on
or a URI in the form
.Sm off
.No scp:// Oo user @ Oc host Oo : port Oc Op / path .
.Sm on
Local file names can be made explicit using absolute or relative pathnames
to avoid
.Nm
treating file names containing
.Sq :\&
as host specifiers.
.Pp
When copying between two remote hosts, if the URI format is used, a
.Ar port
may only be specified on the
.Ar target
if the
.Fl 3
option is used.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl 3
Copies between two remote hosts are transferred through the local host.
Without this option the data is copied directly between the two remote
hosts.
Note that this option disables the progress meter.
.It Fl 4
Forces
.Nm
to use IPv4 addresses only.
.It Fl 6
Forces
.Nm
to use IPv6 addresses only.
.It Fl B
Selects batch mode (prevents asking for passwords or passphrases).
.It Fl C
Compression enable.
Passes the
.Fl C
flag to
.Xr ssh 1
to enable compression.
.It Fl c Ar cipher
Selects the cipher to use for encrypting the data transfer.
This option is directly passed to
.Xr ssh 1 .
.It Fl F Ar ssh_config
Specifies an alternative
per-user configuration file for
.Nm ssh .
This option is directly passed to
.Xr ssh 1 .
.It Fl i Ar identity_file
Selects the file from which the identity (private key) for public key
authentication is read.
This option is directly passed to
.Xr ssh 1 .
+.It Fl J Ar destination
+Connect to the target host by first making an
+.Nm
+connection to the jump host described by
+.Ar destination
+and then establishing a TCP forwarding to the ultimate destination from
+there.
+Multiple jump hops may be specified separated by comma characters.
+This is a shortcut to specify a
+.Cm ProxyJump
+configuration directive.
+This option is directly passed to
+.Xr ssh 1 .
.It Fl l Ar limit
Limits the used bandwidth, specified in Kbit/s.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
in the format used in
.Xr ssh_config 5 .
This is useful for specifying options
for which there is no separate
.Nm scp
command-line flag.
For full details of the options listed below, and their possible values, see
.Xr ssh_config 5 .
.Pp
.Bl -tag -width Ds -offset indent -compact
.It AddressFamily
.It BatchMode
.It BindAddress
.It BindInterface
.It CanonicalDomains
.It CanonicalizeFallbackLocal
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
.It CASignatureAlgorithms
.It CertificateFile
.It ChallengeResponseAuthentication
.It CheckHostIP
.It Ciphers
.It Compression
.It ConnectionAttempts
.It ConnectTimeout
.It ControlMaster
.It ControlPath
.It ControlPersist
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
.It HostbasedAuthentication
.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
.It HostName
.It IdentitiesOnly
.It IdentityAgent
.It IdentityFile
.It IPQoS
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
.It KexAlgorithms
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
.It NumberOfPasswordPrompts
.It PasswordAuthentication
.It PKCS11Provider
.It Port
.It PreferredAuthentications
.It ProxyCommand
.It ProxyJump
.It PubkeyAcceptedKeyTypes
.It PubkeyAuthentication
.It RekeyLimit
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
.It SetEnv
.It StrictHostKeyChecking
.It TCPKeepAlive
.It UpdateHostKeys
.It User
.It UserKnownHostsFile
.It VerifyHostKeyDNS
.El
.It Fl P Ar port
Specifies the port to connect to on the remote host.
Note that this option is written with a capital
.Sq P ,
because
.Fl p
is already reserved for preserving the times and modes of the file.
.It Fl p
Preserves modification times, access times, and modes from the
original file.
.It Fl q
Quiet mode: disables the progress meter as well as warning and diagnostic
messages from
.Xr ssh 1 .
.It Fl r
Recursively copy entire directories.
Note that
.Nm
follows symbolic links encountered in the tree traversal.
.It Fl S Ar program
Name of
.Ar program
to use for the encrypted connection.
The program must understand
.Xr ssh 1
options.
.It Fl T
Disable strict filename checking.
By default when copying files from a remote host to a local directory
.Nm
checks that the received filenames match those requested on the command-line
to prevent the remote end from sending unexpected or unwanted files.
Because of differences in how various operating systems and shells interpret
filename wildcards, these checks may cause wanted files to be rejected.
This option disables these checks at the expense of fully trusting that
the server will not send unexpected filenames.
.It Fl v
Verbose mode.
Causes
.Nm
and
.Xr ssh 1
to print debugging messages about their progress.
This is helpful in
debugging connection, authentication, and configuration problems.
.El
.Sh EXIT STATUS
.Ex -std scp
.Sh SEE ALSO
.Xr sftp 1 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh_config 5 ,
.Xr sshd 8
.Sh HISTORY
.Nm
is based on the rcp program in
.Bx
source code from the Regents of the University of California.
.Sh AUTHORS
.An Timo Rinne Aq Mt tri@iki.fi
.An Tatu Ylonen Aq Mt ylo@cs.hut.fi
diff --git a/scp.c b/scp.c
index 54ff62e76c45..80bc0e8b16d1 100644
--- a/scp.c
+++ b/scp.c
@@ -1,1704 +1,1710 @@
/* $OpenBSD: scp.c,v 1.204 2019/02/10 11:15:52 djm Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
*
* NOTE: This version should NOT be suid root. (This uses ssh to
* do the transfer and ssh has the necessary privileges.)
*
* 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/*
* Copyright (c) 1999 Theo de Raadt. All rights reserved.
* Copyright (c) 1999 Aaron Campbell. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Parts from:
*
* Copyright (c) 1983, 1990, 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#else
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/wait.h>
#include <sys/uio.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <limits.h>
#include <locale.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
#endif
#include "xmalloc.h"
#include "ssh.h"
#include "atomicio.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "progressmeter.h"
#include "utf8.h"
extern char *__progname;
#define COPY_BUFLEN 16384
int do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout);
int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout);
/* Struct for addargs */
arglist args;
arglist remote_remote_args;
/* Bandwidth limit */
long long limit_kbps = 0;
struct bwlimit bwlimit;
/* Name of current file being transferred. */
char *curfile;
/* This is set to non-zero to enable verbose mode. */
int verbose_mode = 0;
/* This is set to zero if the progressmeter is not desired. */
int showprogress = 1;
/*
* This is set to non-zero if remote-remote copy should be piped
* through this process.
*/
int throughlocal = 0;
/* Non-standard port to use for the ssh connection or -1. */
int sshport = -1;
/* This is the program to execute for the secured connection. ("ssh" or -S) */
char *ssh_program = _PATH_SSH_PROGRAM;
/* This is used to store the pid of ssh_program */
pid_t do_cmd_pid = -1;
static void
killchild(int signo)
{
if (do_cmd_pid > 1) {
kill(do_cmd_pid, signo ? signo : SIGTERM);
waitpid(do_cmd_pid, NULL, 0);
}
if (signo)
_exit(1);
exit(1);
}
static void
suspchild(int signo)
{
int status;
if (do_cmd_pid > 1) {
kill(do_cmd_pid, signo);
while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 &&
errno == EINTR)
;
kill(getpid(), SIGSTOP);
}
}
static int
do_local_cmd(arglist *a)
{
u_int i;
int status;
pid_t pid;
if (a->num == 0)
fatal("do_local_cmd: no arguments");
if (verbose_mode) {
fprintf(stderr, "Executing:");
for (i = 0; i < a->num; i++)
fmprintf(stderr, " %s", a->list[i]);
fprintf(stderr, "\n");
}
if ((pid = fork()) == -1)
fatal("do_local_cmd: fork: %s", strerror(errno));
if (pid == 0) {
execvp(a->list[0], a->list);
perror(a->list[0]);
exit(1);
}
do_cmd_pid = pid;
signal(SIGTERM, killchild);
signal(SIGINT, killchild);
signal(SIGHUP, killchild);
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("do_local_cmd: waitpid: %s", strerror(errno));
do_cmd_pid = -1;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
return (-1);
return (0);
}
/*
* This function executes the given command as the specified user on the
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
* assigns the input and output file descriptors on success.
*/
int
do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
{
int pin[2], pout[2], reserved[2];
if (verbose_mode)
fmprintf(stderr,
"Executing: program %s host %s, user %s, command %s\n",
ssh_program, host,
remuser ? remuser : "(unspecified)", cmd);
if (port == -1)
port = sshport;
/*
* Reserve two descriptors so that the real pipes won't get
* descriptors 0 and 1 because that will screw up dup2 below.
*/
if (pipe(reserved) < 0)
fatal("pipe: %s", strerror(errno));
/* Create a socket pair for communicating with ssh. */
if (pipe(pin) < 0)
fatal("pipe: %s", strerror(errno));
if (pipe(pout) < 0)
fatal("pipe: %s", strerror(errno));
/* Free the reserved descriptors. */
close(reserved[0]);
close(reserved[1]);
signal(SIGTSTP, suspchild);
signal(SIGTTIN, suspchild);
signal(SIGTTOU, suspchild);
/* Fork a child to execute the command on the remote host using ssh. */
do_cmd_pid = fork();
if (do_cmd_pid == 0) {
/* Child. */
close(pin[1]);
close(pout[0]);
dup2(pin[0], 0);
dup2(pout[1], 1);
close(pin[0]);
close(pout[1]);
replacearg(&args, 0, "%s", ssh_program);
if (port != -1) {
addargs(&args, "-p");
addargs(&args, "%d", port);
}
if (remuser != NULL) {
addargs(&args, "-l");
addargs(&args, "%s", remuser);
}
addargs(&args, "--");
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
execvp(ssh_program, args.list);
perror(ssh_program);
exit(1);
} else if (do_cmd_pid == -1) {
fatal("fork: %s", strerror(errno));
}
/* Parent. Close the other side, and return the local side. */
close(pin[0]);
*fdout = pin[1];
close(pout[1]);
*fdin = pout[0];
signal(SIGTERM, killchild);
signal(SIGINT, killchild);
signal(SIGHUP, killchild);
return 0;
}
/*
* This function executes a command similar to do_cmd(), but expects the
* input and output descriptors to be setup by a previous call to do_cmd().
* This way the input and output of two commands can be connected.
*/
int
do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout)
{
pid_t pid;
int status;
if (verbose_mode)
fmprintf(stderr,
"Executing: 2nd program %s host %s, user %s, command %s\n",
ssh_program, host,
remuser ? remuser : "(unspecified)", cmd);
if (port == -1)
port = sshport;
/* Fork a child to execute the command on the remote host using ssh. */
pid = fork();
if (pid == 0) {
dup2(fdin, 0);
dup2(fdout, 1);
replacearg(&args, 0, "%s", ssh_program);
if (port != -1) {
addargs(&args, "-p");
addargs(&args, "%d", port);
}
if (remuser != NULL) {
addargs(&args, "-l");
addargs(&args, "%s", remuser);
}
addargs(&args, "--");
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
execvp(ssh_program, args.list);
perror(ssh_program);
exit(1);
} else if (pid == -1) {
fatal("fork: %s", strerror(errno));
}
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("do_cmd2: waitpid: %s", strerror(errno));
return 0;
}
typedef struct {
size_t cnt;
char *buf;
} BUF;
BUF *allocbuf(BUF *, int, int);
void lostconn(int);
int okname(char *);
void run_err(const char *,...);
void verifydir(char *);
struct passwd *pwd;
uid_t userid;
int errs, remin, remout;
int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
#define CMDNEEDS 64
char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
int response(void);
void rsource(char *, struct stat *);
void sink(int, char *[], const char *);
void source(int, char *[]);
void tolocal(int, char *[]);
void toremote(int, char *[]);
void usage(void);
int
main(int argc, char **argv)
{
int ch, fflag, tflag, status, n;
char **newargv;
const char *errstr;
extern char *optarg;
extern int optind;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ seed_rng();
+
msetlocale();
/* Copy argv, because we modify it */
newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
for (n = 0; n < argc; n++)
newargv[n] = xstrdup(argv[n]);
argv = newargv;
__progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args));
memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
args.list = remote_remote_args.list = NULL;
addargs(&args, "%s", ssh_program);
addargs(&args, "-x");
addargs(&args, "-oForwardAgent=no");
addargs(&args, "-oPermitLocalCommand=no");
addargs(&args, "-oClearAllForwardings=yes");
addargs(&args, "-oRemoteCommand=none");
addargs(&args, "-oRequestTTY=no");
fflag = Tflag = tflag = 0;
while ((ch = getopt(argc, argv,
- "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
+ "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) {
switch (ch) {
/* User-visible flags. */
case '1':
fatal("SSH protocol v.1 is no longer supported");
break;
case '2':
/* Ignored */
break;
case '4':
case '6':
case 'C':
addargs(&args, "-%c", ch);
addargs(&remote_remote_args, "-%c", ch);
break;
case '3':
throughlocal = 1;
break;
case 'o':
case 'c':
case 'i':
case 'F':
+ case 'J':
addargs(&remote_remote_args, "-%c", ch);
addargs(&remote_remote_args, "%s", optarg);
addargs(&args, "-%c", ch);
addargs(&args, "%s", optarg);
break;
case 'P':
sshport = a2port(optarg);
if (sshport <= 0)
fatal("bad port \"%s\"\n", optarg);
break;
case 'B':
addargs(&remote_remote_args, "-oBatchmode=yes");
addargs(&args, "-oBatchmode=yes");
break;
case 'l':
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
&errstr);
if (errstr != NULL)
usage();
limit_kbps *= 1024; /* kbps */
bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN);
break;
case 'p':
pflag = 1;
break;
case 'r':
iamrecursive = 1;
break;
case 'S':
ssh_program = xstrdup(optarg);
break;
case 'v':
addargs(&args, "-v");
addargs(&remote_remote_args, "-v");
verbose_mode = 1;
break;
case 'q':
addargs(&args, "-q");
addargs(&remote_remote_args, "-q");
showprogress = 0;
break;
/* Server options. */
case 'd':
targetshouldbedirectory = 1;
break;
case 'f': /* "from" */
iamremote = 1;
fflag = 1;
break;
case 't': /* "to" */
iamremote = 1;
tflag = 1;
#ifdef HAVE_CYGWIN
setmode(0, O_BINARY);
#endif
break;
case 'T':
Tflag = 1;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if ((pwd = getpwuid(userid = getuid())) == NULL)
fatal("unknown user %u", (u_int) userid);
if (!isatty(STDOUT_FILENO))
showprogress = 0;
if (pflag) {
/* Cannot pledge: -p allows setuid/setgid files... */
} else {
if (pledge("stdio rpath wpath cpath fattr tty proc exec",
NULL) == -1) {
perror("pledge");
exit(1);
}
}
remin = STDIN_FILENO;
remout = STDOUT_FILENO;
if (fflag) {
/* Follow "protocol", send data. */
(void) response();
source(argc, argv);
exit(errs != 0);
}
if (tflag) {
/* Receive data. */
sink(argc, argv, NULL);
exit(errs != 0);
}
if (argc < 2)
usage();
if (argc > 2)
targetshouldbedirectory = 1;
remin = remout = -1;
do_cmd_pid = -1;
/* Command to be executed on remote system using "ssh". */
(void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
verbose_mode ? " -v" : "",
iamrecursive ? " -r" : "", pflag ? " -p" : "",
targetshouldbedirectory ? " -d" : "");
(void) signal(SIGPIPE, lostconn);
if (colon(argv[argc - 1])) /* Dest is remote host. */
toremote(argc, argv);
else {
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
tolocal(argc, argv); /* Dest is local host. */
}
/*
* Finally check the exit status of the ssh process, if one was forked
* and no error has occurred yet
*/
if (do_cmd_pid != -1 && errs == 0) {
if (remin != -1)
(void) close(remin);
if (remout != -1)
(void) close(remout);
if (waitpid(do_cmd_pid, &status, 0) == -1)
errs = 1;
else {
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
errs = 1;
}
}
exit(errs != 0);
}
/* Callback from atomicio6 to update progress meter and limit bandwidth */
static int
scpio(void *_cnt, size_t s)
{
off_t *cnt = (off_t *)_cnt;
*cnt += s;
+ refresh_progress_meter(0);
if (limit_kbps > 0)
bandwidth_limit(&bwlimit, s);
return 0;
}
static int
do_times(int fd, int verb, const struct stat *sb)
{
/* strlen(2^64) == 20; strlen(10^6) == 7 */
char buf[(20 + 7 + 2) * 2 + 2];
(void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n",
(unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime),
(unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime));
if (verb) {
fprintf(stderr, "File mtime %lld atime %lld\n",
(long long)sb->st_mtime, (long long)sb->st_atime);
fprintf(stderr, "Sending file timestamps: %s", buf);
}
(void) atomicio(vwrite, fd, buf, strlen(buf));
return (response());
}
static int
parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
char **pathp)
{
int r;
r = parse_uri("scp", uri, userp, hostp, portp, pathp);
if (r == 0 && *pathp == NULL)
*pathp = xstrdup(".");
return r;
}
/* Appends a string to an array; returns 0 on success, -1 on alloc failure */
static int
append(char *cp, char ***ap, size_t *np)
{
char **tmp;
if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
return -1;
tmp[(*np)] = cp;
(*np)++;
*ap = tmp;
return 0;
}
/*
* Finds the start and end of the first brace pair in the pattern.
* returns 0 on success or -1 for invalid patterns.
*/
static int
find_brace(const char *pattern, int *startp, int *endp)
{
int i;
int in_bracket, brace_level;
*startp = *endp = -1;
in_bracket = brace_level = 0;
for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
switch (pattern[i]) {
case '\\':
/* skip next character */
if (pattern[i + 1] != '\0')
i++;
break;
case '[':
in_bracket = 1;
break;
case ']':
in_bracket = 0;
break;
case '{':
if (in_bracket)
break;
if (pattern[i + 1] == '}') {
/* Protect a single {}, for find(1), like csh */
i++; /* skip */
break;
}
if (*startp == -1)
*startp = i;
brace_level++;
break;
case '}':
if (in_bracket)
break;
if (*startp < 0) {
/* Unbalanced brace */
return -1;
}
if (--brace_level <= 0)
*endp = i;
break;
}
}
/* unbalanced brackets/braces */
if (*endp < 0 && (*startp >= 0 || in_bracket))
return -1;
return 0;
}
/*
* Assembles and records a successfully-expanded pattern, returns -1 on
* alloc failure.
*/
static int
emit_expansion(const char *pattern, int brace_start, int brace_end,
int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
{
char *cp;
int o = 0, tail_len = strlen(pattern + brace_end + 1);
if ((cp = malloc(brace_start + (sel_end - sel_start) +
tail_len + 1)) == NULL)
return -1;
/* Pattern before initial brace */
if (brace_start > 0) {
memcpy(cp, pattern, brace_start);
o = brace_start;
}
/* Current braced selection */
if (sel_end - sel_start > 0) {
memcpy(cp + o, pattern + sel_start,
sel_end - sel_start);
o += sel_end - sel_start;
}
/* Remainder of pattern after closing brace */
if (tail_len > 0) {
memcpy(cp + o, pattern + brace_end + 1, tail_len);
o += tail_len;
}
cp[o] = '\0';
if (append(cp, patternsp, npatternsp) != 0) {
free(cp);
return -1;
}
return 0;
}
/*
* Expand the first encountered brace in pattern, appending the expanded
* patterns it yielded to the *patternsp array.
*
* Returns 0 on success or -1 on allocation failure.
*
* Signals whether expansion was performed via *expanded and whether
* pattern was invalid via *invalid.
*/
static int
brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
int *expanded, int *invalid)
{
int i;
int in_bracket, brace_start, brace_end, brace_level;
int sel_start, sel_end;
*invalid = *expanded = 0;
if (find_brace(pattern, &brace_start, &brace_end) != 0) {
*invalid = 1;
return 0;
} else if (brace_start == -1)
return 0;
in_bracket = brace_level = 0;
for (i = sel_start = brace_start + 1; i < brace_end; i++) {
switch (pattern[i]) {
case '{':
if (in_bracket)
break;
brace_level++;
break;
case '}':
if (in_bracket)
break;
brace_level--;
break;
case '[':
in_bracket = 1;
break;
case ']':
in_bracket = 0;
break;
case '\\':
if (i < brace_end - 1)
i++; /* skip */
break;
}
if (pattern[i] == ',' || i == brace_end - 1) {
if (in_bracket || brace_level > 0)
continue;
/* End of a selection, emit an expanded pattern */
/* Adjust end index for last selection */
sel_end = (i == brace_end - 1) ? brace_end : i;
if (emit_expansion(pattern, brace_start, brace_end,
sel_start, sel_end, patternsp, npatternsp) != 0)
return -1;
/* move on to the next selection */
sel_start = i + 1;
continue;
}
}
if (in_bracket || brace_level > 0) {
*invalid = 1;
return 0;
}
/* success */
*expanded = 1;
return 0;
}
/* Expand braces from pattern. Returns 0 on success, -1 on failure */
static int
brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
{
char *cp, *cp2, **active = NULL, **done = NULL;
size_t i, nactive = 0, ndone = 0;
int ret = -1, invalid = 0, expanded = 0;
*patternsp = NULL;
*npatternsp = 0;
/* Start the worklist with the original pattern */
if ((cp = strdup(pattern)) == NULL)
return -1;
if (append(cp, &active, &nactive) != 0) {
free(cp);
return -1;
}
while (nactive > 0) {
cp = active[nactive - 1];
nactive--;
if (brace_expand_one(cp, &active, &nactive,
&expanded, &invalid) == -1) {
free(cp);
goto fail;
}
if (invalid)
fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
if (expanded) {
/*
* Current entry expanded to new entries on the
* active list; discard the progenitor pattern.
*/
free(cp);
continue;
}
/*
* Pattern did not expand; append the finename component to
* the completed list
*/
if ((cp2 = strrchr(cp, '/')) != NULL)
*cp2++ = '\0';
else
cp2 = cp;
if (append(xstrdup(cp2), &done, &ndone) != 0) {
free(cp);
goto fail;
}
free(cp);
}
/* success */
*patternsp = done;
*npatternsp = ndone;
done = NULL;
ndone = 0;
ret = 0;
fail:
for (i = 0; i < nactive; i++)
free(active[i]);
free(active);
for (i = 0; i < ndone; i++)
free(done[i]);
free(done);
return ret;
}
void
toremote(int argc, char **argv)
{
char *suser = NULL, *host = NULL, *src = NULL;
char *bp, *tuser, *thost, *targ;
int sport = -1, tport = -1;
arglist alist;
int i, r;
u_int j;
memset(&alist, '\0', sizeof(alist));
alist.list = NULL;
/* Parse target */
r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ);
if (r == -1) {
fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]);
++errs;
goto out;
}
if (r != 0) {
if (parse_user_host_path(argv[argc - 1], &tuser, &thost,
&targ) == -1) {
fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]);
++errs;
goto out;
}
}
if (tuser != NULL && !okname(tuser)) {
++errs;
goto out;
}
/* Parse source files */
for (i = 0; i < argc - 1; i++) {
free(suser);
free(host);
free(src);
r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
if (r == -1) {
fmprintf(stderr, "%s: invalid uri\n", argv[i]);
++errs;
continue;
}
if (r != 0) {
parse_user_host_path(argv[i], &suser, &host, &src);
}
if (suser != NULL && !okname(suser)) {
++errs;
continue;
}
if (host && throughlocal) { /* extended remote to remote */
xasprintf(&bp, "%s -f %s%s", cmd,
*src == '-' ? "-- " : "", src);
if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0)
exit(1);
free(bp);
xasprintf(&bp, "%s -t %s%s", cmd,
*targ == '-' ? "-- " : "", targ);
if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0)
exit(1);
free(bp);
(void) close(remin);
(void) close(remout);
remin = remout = -1;
} else if (host) { /* standard remote to remote */
if (tport != -1 && tport != SSH_DEFAULT_PORT) {
/* This would require the remote support URIs */
fatal("target port not supported with two "
"remote hosts without the -3 option");
}
freeargs(&alist);
addargs(&alist, "%s", ssh_program);
addargs(&alist, "-x");
addargs(&alist, "-oClearAllForwardings=yes");
addargs(&alist, "-n");
for (j = 0; j < remote_remote_args.num; j++) {
addargs(&alist, "%s",
remote_remote_args.list[j]);
}
if (sport != -1) {
addargs(&alist, "-p");
addargs(&alist, "%d", sport);
}
if (suser) {
addargs(&alist, "-l");
addargs(&alist, "%s", suser);
}
addargs(&alist, "--");
addargs(&alist, "%s", host);
addargs(&alist, "%s", cmd);
addargs(&alist, "%s", src);
addargs(&alist, "%s%s%s:%s",
tuser ? tuser : "", tuser ? "@" : "",
thost, targ);
if (do_local_cmd(&alist) != 0)
errs = 1;
} else { /* local to remote */
if (remin == -1) {
xasprintf(&bp, "%s -t %s%s", cmd,
*targ == '-' ? "-- " : "", targ);
if (do_cmd(thost, tuser, tport, bp, &remin,
&remout) < 0)
exit(1);
if (response() < 0)
exit(1);
free(bp);
}
source(1, argv + i);
}
}
out:
free(tuser);
free(thost);
free(targ);
free(suser);
free(host);
free(src);
}
void
tolocal(int argc, char **argv)
{
char *bp, *host = NULL, *src = NULL, *suser = NULL;
arglist alist;
int i, r, sport = -1;
memset(&alist, '\0', sizeof(alist));
alist.list = NULL;
for (i = 0; i < argc - 1; i++) {
free(suser);
free(host);
free(src);
r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
if (r == -1) {
fmprintf(stderr, "%s: invalid uri\n", argv[i]);
++errs;
continue;
}
if (r != 0)
parse_user_host_path(argv[i], &suser, &host, &src);
if (suser != NULL && !okname(suser)) {
++errs;
continue;
}
if (!host) { /* Local to local. */
freeargs(&alist);
addargs(&alist, "%s", _PATH_CP);
if (iamrecursive)
addargs(&alist, "-r");
if (pflag)
addargs(&alist, "-p");
addargs(&alist, "--");
addargs(&alist, "%s", argv[i]);
addargs(&alist, "%s", argv[argc-1]);
if (do_local_cmd(&alist))
++errs;
continue;
}
/* Remote to local. */
xasprintf(&bp, "%s -f %s%s",
cmd, *src == '-' ? "-- " : "", src);
if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) {
free(bp);
++errs;
continue;
}
free(bp);
sink(1, argv + argc - 1, src);
(void) close(remin);
remin = remout = -1;
}
free(suser);
free(host);
free(src);
}
void
source(int argc, char **argv)
{
struct stat stb;
static BUF buffer;
BUF *bp;
off_t i, statbytes;
size_t amt, nr;
int fd = -1, haderr, indx;
char *last, *name, buf[2048], encname[PATH_MAX];
int len;
for (indx = 0; indx < argc; ++indx) {
name = argv[indx];
statbytes = 0;
len = strlen(name);
while (len > 1 && name[len-1] == '/')
name[--len] = '\0';
if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) < 0)
goto syserr;
if (strchr(name, '\n') != NULL) {
strnvis(encname, name, sizeof(encname), VIS_NL);
name = encname;
}
if (fstat(fd, &stb) < 0) {
syserr: run_err("%s: %s", name, strerror(errno));
goto next;
}
if (stb.st_size < 0) {
run_err("%s: %s", name, "Negative file size");
goto next;
}
unset_nonblock(fd);
switch (stb.st_mode & S_IFMT) {
case S_IFREG:
break;
case S_IFDIR:
if (iamrecursive) {
rsource(name, &stb);
goto next;
}
/* FALLTHROUGH */
default:
run_err("%s: not a regular file", name);
goto next;
}
if ((last = strrchr(name, '/')) == NULL)
last = name;
else
++last;
curfile = last;
if (pflag) {
if (do_times(remout, verbose_mode, &stb) < 0)
goto next;
}
#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
snprintf(buf, sizeof buf, "C%04o %lld %s\n",
(u_int) (stb.st_mode & FILEMODEMASK),
(long long)stb.st_size, last);
if (verbose_mode)
fmprintf(stderr, "Sending file modes: %s", buf);
(void) atomicio(vwrite, remout, buf, strlen(buf));
if (response() < 0)
goto next;
if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
next: if (fd != -1) {
(void) close(fd);
fd = -1;
}
continue;
}
if (showprogress)
start_progress_meter(curfile, stb.st_size, &statbytes);
set_nonblock(remout);
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
amt = bp->cnt;
if (i + (off_t)amt > stb.st_size)
amt = stb.st_size - i;
if (!haderr) {
if ((nr = atomicio(read, fd,
bp->buf, amt)) != amt) {
haderr = errno;
memset(bp->buf + nr, 0, amt - nr);
}
}
/* Keep writing after error to retain sync */
if (haderr) {
(void)atomicio(vwrite, remout, bp->buf, amt);
memset(bp->buf, 0, amt);
continue;
}
if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
&statbytes) != amt)
haderr = errno;
}
unset_nonblock(remout);
if (fd != -1) {
if (close(fd) < 0 && !haderr)
haderr = errno;
fd = -1;
}
if (!haderr)
(void) atomicio(vwrite, remout, "", 1);
else
run_err("%s: %s", name, strerror(haderr));
(void) response();
if (showprogress)
stop_progress_meter();
}
}
void
rsource(char *name, struct stat *statp)
{
DIR *dirp;
struct dirent *dp;
char *last, *vect[1], path[PATH_MAX];
if (!(dirp = opendir(name))) {
run_err("%s: %s", name, strerror(errno));
return;
}
last = strrchr(name, '/');
if (last == NULL)
last = name;
else
last++;
if (pflag) {
if (do_times(remout, verbose_mode, statp) < 0) {
closedir(dirp);
return;
}
}
(void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
(u_int) (statp->st_mode & FILEMODEMASK), 0, last);
if (verbose_mode)
fmprintf(stderr, "Entering directory: %s", path);
(void) atomicio(vwrite, remout, path, strlen(path));
if (response() < 0) {
closedir(dirp);
return;
}
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_ino == 0)
continue;
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
run_err("%s/%s: name too long", name, dp->d_name);
continue;
}
(void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
vect[0] = path;
source(1, vect);
}
(void) closedir(dirp);
(void) atomicio(vwrite, remout, "E\n", 2);
(void) response();
}
#define TYPE_OVERFLOW(type, val) \
((sizeof(type) == 4 && (val) > INT32_MAX) || \
(sizeof(type) == 8 && (val) > INT64_MAX) || \
(sizeof(type) != 4 && sizeof(type) != 8))
void
sink(int argc, char **argv, const char *src)
{
static BUF buffer;
struct stat stb;
enum {
YES, NO, DISPLAYED
} wrerr;
BUF *bp;
off_t i;
size_t j, count;
int amt, exists, first, ofd;
mode_t mode, omode, mask;
off_t size, statbytes;
unsigned long long ull;
int setimes, targisdir, wrerrno = 0;
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
char **patterns = NULL;
size_t n, npatterns = 0;
struct timeval tv[2];
#define atime tv[0]
#define mtime tv[1]
#define SCREWUP(str) { why = str; goto screwup; }
if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
SCREWUP("Unexpected off_t/time_t size");
setimes = targisdir = 0;
mask = umask(0);
if (!pflag)
(void) umask(mask);
if (argc != 1) {
run_err("ambiguous target");
exit(1);
}
targ = *argv;
if (targetshouldbedirectory)
verifydir(targ);
(void) atomicio(vwrite, remout, "", 1);
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
targisdir = 1;
if (src != NULL && !iamrecursive && !Tflag) {
/*
* Prepare to try to restrict incoming filenames to match
* the requested destination file glob.
*/
if (brace_expand(src, &patterns, &npatterns) != 0)
fatal("%s: could not expand pattern", __func__);
}
for (first = 1;; first = 0) {
cp = buf;
if (atomicio(read, remin, cp, 1) != 1)
goto done;
if (*cp++ == '\n')
SCREWUP("unexpected <newline>");
do {
if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
SCREWUP("lost connection");
*cp++ = ch;
} while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
*cp = 0;
if (verbose_mode)
fmprintf(stderr, "Sink: %s", buf);
if (buf[0] == '\01' || buf[0] == '\02') {
if (iamremote == 0) {
(void) snmprintf(visbuf, sizeof(visbuf),
NULL, "%s", buf + 1);
(void) atomicio(vwrite, STDERR_FILENO,
visbuf, strlen(visbuf));
}
if (buf[0] == '\02')
exit(1);
++errs;
continue;
}
if (buf[0] == 'E') {
(void) atomicio(vwrite, remout, "", 1);
goto done;
}
if (ch == '\n')
*--cp = 0;
cp = buf;
if (*cp == 'T') {
setimes++;
cp++;
if (!isdigit((unsigned char)*cp))
SCREWUP("mtime.sec not present");
ull = strtoull(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("mtime.sec not delimited");
if (TYPE_OVERFLOW(time_t, ull))
setimes = 0; /* out of range */
mtime.tv_sec = ull;
mtime.tv_usec = strtol(cp, &cp, 10);
if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 ||
mtime.tv_usec > 999999)
SCREWUP("mtime.usec not delimited");
if (!isdigit((unsigned char)*cp))
SCREWUP("atime.sec not present");
ull = strtoull(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("atime.sec not delimited");
if (TYPE_OVERFLOW(time_t, ull))
setimes = 0; /* out of range */
atime.tv_sec = ull;
atime.tv_usec = strtol(cp, &cp, 10);
if (!cp || *cp++ != '\0' || atime.tv_usec < 0 ||
atime.tv_usec > 999999)
SCREWUP("atime.usec not delimited");
(void) atomicio(vwrite, remout, "", 1);
continue;
}
if (*cp != 'C' && *cp != 'D') {
/*
* Check for the case "rcp remote:foo\* local:bar".
* In this case, the line "No match." can be returned
* by the shell before the rcp command on the remote is
* executed so the ^Aerror_message convention isn't
* followed.
*/
if (first) {
run_err("%s", cp);
exit(1);
}
SCREWUP("expected control record");
}
mode = 0;
for (++cp; cp < buf + 5; cp++) {
if (*cp < '0' || *cp > '7')
SCREWUP("bad mode");
mode = (mode << 3) | (*cp - '0');
}
if (!pflag)
mode &= ~mask;
if (*cp++ != ' ')
SCREWUP("mode not delimited");
if (!isdigit((unsigned char)*cp))
SCREWUP("size not present");
ull = strtoull(cp, &cp, 10);
if (!cp || *cp++ != ' ')
SCREWUP("size not delimited");
if (TYPE_OVERFLOW(off_t, ull))
SCREWUP("size out of range");
size = (off_t)ull;
- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
+ if (*cp == '\0' || strchr(cp, '/') != NULL ||
+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
run_err("error: unexpected filename: %s", cp);
exit(1);
}
if (npatterns > 0) {
for (n = 0; n < npatterns; n++) {
if (fnmatch(patterns[n], cp, 0) == 0)
break;
}
if (n >= npatterns)
SCREWUP("filename does not match request");
}
if (targisdir) {
static char *namebuf;
static size_t cursize;
size_t need;
need = strlen(targ) + strlen(cp) + 250;
if (need > cursize) {
free(namebuf);
namebuf = xmalloc(need);
cursize = need;
}
(void) snprintf(namebuf, need, "%s%s%s", targ,
strcmp(targ, "/") ? "/" : "", cp);
np = namebuf;
} else
np = targ;
curfile = cp;
exists = stat(np, &stb) == 0;
if (buf[0] == 'D') {
int mod_flag = pflag;
if (!iamrecursive)
SCREWUP("received directory without -r");
if (exists) {
if (!S_ISDIR(stb.st_mode)) {
errno = ENOTDIR;
goto bad;
}
if (pflag)
(void) chmod(np, mode);
} else {
/* Handle copying from a read-only
directory */
mod_flag = 1;
if (mkdir(np, mode | S_IRWXU) < 0)
goto bad;
}
vect[0] = xstrdup(np);
sink(1, vect, src);
if (setimes) {
setimes = 0;
if (utimes(vect[0], tv) < 0)
run_err("%s: set times: %s",
vect[0], strerror(errno));
}
if (mod_flag)
(void) chmod(vect[0], mode);
free(vect[0]);
continue;
}
omode = mode;
mode |= S_IWUSR;
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
bad: run_err("%s: %s", np, strerror(errno));
continue;
}
(void) atomicio(vwrite, remout, "", 1);
if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
(void) close(ofd);
continue;
}
cp = bp->buf;
wrerr = NO;
statbytes = 0;
if (showprogress)
start_progress_meter(curfile, size, &statbytes);
set_nonblock(remin);
for (count = i = 0; i < size; i += bp->cnt) {
amt = bp->cnt;
if (i + amt > size)
amt = size - i;
count += amt;
do {
j = atomicio6(read, remin, cp, amt,
scpio, &statbytes);
if (j == 0) {
run_err("%s", j != EPIPE ?
strerror(errno) :
"dropped connection");
exit(1);
}
amt -= j;
cp += j;
} while (amt > 0);
if (count == bp->cnt) {
/* Keep reading so we stay sync'd up. */
if (wrerr == NO) {
if (atomicio(vwrite, ofd, bp->buf,
count) != count) {
wrerr = YES;
wrerrno = errno;
}
}
count = 0;
cp = bp->buf;
}
}
unset_nonblock(remin);
if (count != 0 && wrerr == NO &&
atomicio(vwrite, ofd, bp->buf, count) != count) {
wrerr = YES;
wrerrno = errno;
}
if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
ftruncate(ofd, size) != 0) {
run_err("%s: truncate: %s", np, strerror(errno));
wrerr = DISPLAYED;
}
if (pflag) {
if (exists || omode != mode)
#ifdef HAVE_FCHMOD
if (fchmod(ofd, omode)) {
#else /* HAVE_FCHMOD */
if (chmod(np, omode)) {
#endif /* HAVE_FCHMOD */
run_err("%s: set mode: %s",
np, strerror(errno));
wrerr = DISPLAYED;
}
} else {
if (!exists && omode != mode)
#ifdef HAVE_FCHMOD
if (fchmod(ofd, omode & ~mask)) {
#else /* HAVE_FCHMOD */
if (chmod(np, omode & ~mask)) {
#endif /* HAVE_FCHMOD */
run_err("%s: set mode: %s",
np, strerror(errno));
wrerr = DISPLAYED;
}
}
if (close(ofd) == -1) {
wrerr = YES;
wrerrno = errno;
}
(void) response();
if (showprogress)
stop_progress_meter();
if (setimes && wrerr == NO) {
setimes = 0;
if (utimes(np, tv) < 0) {
run_err("%s: set times: %s",
np, strerror(errno));
wrerr = DISPLAYED;
}
}
switch (wrerr) {
case YES:
run_err("%s: %s", np, strerror(wrerrno));
break;
case NO:
(void) atomicio(vwrite, remout, "", 1);
break;
case DISPLAYED:
break;
}
}
done:
for (n = 0; n < npatterns; n++)
free(patterns[n]);
free(patterns);
return;
screwup:
for (n = 0; n < npatterns; n++)
free(patterns[n]);
free(patterns);
run_err("protocol error: %s", why);
exit(1);
}
int
response(void)
{
char ch, *cp, resp, rbuf[2048], visbuf[2048];
if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
lostconn(0);
cp = rbuf;
switch (resp) {
case 0: /* ok */
return (0);
default:
*cp++ = resp;
/* FALLTHROUGH */
case 1: /* error, followed by error msg */
case 2: /* fatal error, "" */
do {
if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
lostconn(0);
*cp++ = ch;
} while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
if (!iamremote) {
cp[-1] = '\0';
(void) snmprintf(visbuf, sizeof(visbuf),
NULL, "%s\n", rbuf);
(void) atomicio(vwrite, STDERR_FILENO,
visbuf, strlen(visbuf));
}
++errs;
if (resp == 1)
return (-1);
exit(1);
}
/* NOTREACHED */
}
void
usage(void)
{
(void) fprintf(stderr,
"usage: scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
- " [-l limit] [-o ssh_option] [-P port] [-S program] source ... target\n");
+ " [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
+ " [-S program] source ... target\n");
exit(1);
}
void
run_err(const char *fmt,...)
{
static FILE *fp;
va_list ap;
++errs;
if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) {
(void) fprintf(fp, "%c", 0x01);
(void) fprintf(fp, "scp: ");
va_start(ap, fmt);
(void) vfprintf(fp, fmt, ap);
va_end(ap);
(void) fprintf(fp, "\n");
(void) fflush(fp);
}
if (!iamremote) {
va_start(ap, fmt);
vfmprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
}
void
verifydir(char *cp)
{
struct stat stb;
if (!stat(cp, &stb)) {
if (S_ISDIR(stb.st_mode))
return;
errno = ENOTDIR;
}
run_err("%s: %s", cp, strerror(errno));
killchild(0);
}
int
okname(char *cp0)
{
int c;
char *cp;
cp = cp0;
do {
c = (int)*cp;
if (c & 0200)
goto bad;
if (!isalpha(c) && !isdigit((unsigned char)c)) {
switch (c) {
case '\'':
case '"':
case '`':
case ' ':
case '#':
goto bad;
default:
break;
}
}
} while (*++cp);
return (1);
bad: fmprintf(stderr, "%s: invalid user name\n", cp0);
return (0);
}
BUF *
allocbuf(BUF *bp, int fd, int blksize)
{
size_t size;
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
struct stat stb;
if (fstat(fd, &stb) < 0) {
run_err("fstat: %s", strerror(errno));
return (0);
}
size = ROUNDUP(stb.st_blksize, blksize);
if (size == 0)
size = blksize;
#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */
size = blksize;
#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */
if (bp->cnt >= size)
return (bp);
bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1);
bp->cnt = size;
return (bp);
}
void
lostconn(int signo)
{
if (!iamremote)
(void)write(STDERR_FILENO, "lost connection\n", 16);
if (signo)
_exit(1);
else
exit(1);
}
diff --git a/servconf.c b/servconf.c
index 932d363bbe3d..ffac5d2c7e0b 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,2690 +1,2708 @@
-/* $OpenBSD: servconf.c,v 1.342 2018/09/20 23:40:16 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.350 2019/03/25 22:33:44 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SYSCTL_H
#include <sys/sysctl.h>
#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#ifdef HAVE_NET_ROUTE_H
#include <net/route.h>
#endif
#include <ctype.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <limits.h>
#include <stdarg.h>
#include <errno.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "log.h"
#include "sshbuf.h"
#include "misc.h"
#include "servconf.h"
#include "compat.h"
#include "pathnames.h"
#include "cipher.h"
#include "sshkey.h"
#include "kex.h"
#include "mac.h"
#include "match.h"
#include "channels.h"
#include "groupaccess.h"
#include "canohost.h"
#include "packet.h"
#include "ssherr.h"
#include "hostfile.h"
#include "auth.h"
#include "myproposal.h"
#include "digest.h"
static void add_listen_addr(ServerOptions *, const char *,
const char *, int);
static void add_one_listen_addr(ServerOptions *, const char *,
const char *, int);
/* Use of privilege separation or not */
extern int use_privsep;
extern struct sshbuf *cfg;
/* Initializes the server options to their default values. */
void
initialize_server_options(ServerOptions *options)
{
memset(options, 0, sizeof(*options));
/* Portable-specific options */
options->use_pam = -1;
/* Standard Options */
options->num_ports = 0;
options->ports_from_cmdline = 0;
options->queued_listen_addrs = NULL;
options->num_queued_listens = 0;
options->listen_addrs = NULL;
options->num_listen_addrs = 0;
options->address_family = -1;
options->routing_domain = NULL;
options->num_host_key_files = 0;
options->num_host_cert_files = 0;
options->host_key_agent = NULL;
options->pid_file = NULL;
options->login_grace_time = -1;
options->permit_root_login = PERMIT_NOT_SET;
options->ignore_rhosts = -1;
options->ignore_user_known_hosts = -1;
options->print_motd = -1;
options->print_lastlog = -1;
options->x11_forwarding = -1;
options->x11_display_offset = -1;
options->x11_use_localhost = -1;
options->permit_tty = -1;
options->permit_user_rc = -1;
options->xauth_location = NULL;
options->strict_modes = -1;
options->tcp_keep_alive = -1;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
options->hostbased_authentication = -1;
options->hostbased_uses_name_from_packet_only = -1;
options->hostbased_key_types = NULL;
options->hostkeyalgorithms = NULL;
options->pubkey_authentication = -1;
options->pubkey_key_types = NULL;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
options->kerberos_get_afs_token = -1;
options->gss_authentication=-1;
options->gss_cleanup_creds = -1;
options->gss_strict_acceptor = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->permit_user_env = -1;
options->permit_user_env_whitelist = NULL;
options->compression = -1;
options->rekey_limit = -1;
options->rekey_interval = -1;
options->allow_tcp_forwarding = -1;
options->allow_streamlocal_forwarding = -1;
options->allow_agent_forwarding = -1;
options->num_allow_users = 0;
options->num_deny_users = 0;
options->num_allow_groups = 0;
options->num_deny_groups = 0;
options->ciphers = NULL;
options->macs = NULL;
options->kex_algorithms = NULL;
options->ca_sign_algorithms = NULL;
options->fwd_opts.gateway_ports = -1;
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
options->num_subsystems = 0;
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1;
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
options->use_dns = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
options->num_authkeys_files = 0;
options->num_accept_env = 0;
options->num_setenv = 0;
options->permit_tun = -1;
options->permitted_opens = NULL;
options->permitted_listens = NULL;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
options->authorized_keys_command = NULL;
options->authorized_keys_command_user = NULL;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
options->authorized_principals_command = NULL;
options->authorized_principals_command_user = NULL;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->fingerprint_hash = -1;
options->disable_forwarding = -1;
options->expose_userauth_info = -1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
static int
option_clear_or_none(const char *o)
{
return o == NULL || strcasecmp(o, "none") == 0;
}
static void
assemble_algorithms(ServerOptions *o)
{
char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
int r;
all_cipher = cipher_alg_list(',', 0);
all_mac = mac_alg_list(',');
all_kex = kex_alg_list(',');
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
} while (0)
ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher);
ASSEMBLE(macs, KEX_SERVER_MAC, all_mac);
ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex);
ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key);
ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key);
ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key);
ASSEMBLE(ca_sign_algorithms, SSH_ALLOWED_CA_SIGALGS, all_sig);
#undef ASSEMBLE
free(all_cipher);
free(all_mac);
free(all_kex);
free(all_key);
free(all_sig);
}
static void
-array_append(const char *file, const int line, const char *directive,
- char ***array, u_int *lp, const char *s)
+array_append2(const char *file, const int line, const char *directive,
+ char ***array, int **iarray, u_int *lp, const char *s, int i)
{
if (*lp >= INT_MAX)
fatal("%s line %d: Too many %s entries", file, line, directive);
+ if (iarray != NULL) {
+ *iarray = xrecallocarray(*iarray, *lp, *lp + 1,
+ sizeof(**iarray));
+ (*iarray)[*lp] = i;
+ }
+
*array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array));
(*array)[*lp] = xstrdup(s);
(*lp)++;
}
+static void
+array_append(const char *file, const int line, const char *directive,
+ char ***array, u_int *lp, const char *s)
+{
+ array_append2(file, line, directive, array, NULL, lp, s, 0);
+}
+
void
servconf_add_hostkey(const char *file, const int line,
- ServerOptions *options, const char *path)
+ ServerOptions *options, const char *path, int userprovided)
{
char *apath = derelativise_path(path);
- array_append(file, line, "HostKey",
- &options->host_key_files, &options->num_host_key_files, apath);
+ array_append2(file, line, "HostKey",
+ &options->host_key_files, &options->host_key_file_userprovided,
+ &options->num_host_key_files, apath, userprovided);
free(apath);
}
void
servconf_add_hostcert(const char *file, const int line,
ServerOptions *options, const char *path)
{
char *apath = derelativise_path(path);
array_append(file, line, "HostCertificate",
&options->host_cert_files, &options->num_host_cert_files, apath);
free(apath);
}
void
fill_default_server_options(ServerOptions *options)
{
u_int i;
/* Portable-specific options */
if (options->use_pam == -1)
options->use_pam = 0;
/* Standard Options */
if (options->num_host_key_files == 0) {
/* fill default hostkeys for protocols */
servconf_add_hostkey("[default]", 0, options,
- _PATH_HOST_RSA_KEY_FILE);
+ _PATH_HOST_RSA_KEY_FILE, 0);
#ifdef OPENSSL_HAS_ECC
servconf_add_hostkey("[default]", 0, options,
- _PATH_HOST_ECDSA_KEY_FILE);
+ _PATH_HOST_ECDSA_KEY_FILE, 0);
#endif
servconf_add_hostkey("[default]", 0, options,
- _PATH_HOST_ED25519_KEY_FILE);
+ _PATH_HOST_ED25519_KEY_FILE, 0);
#ifdef WITH_XMSS
servconf_add_hostkey("[default]", 0, options,
- _PATH_HOST_XMSS_KEY_FILE);
+ _PATH_HOST_XMSS_KEY_FILE, 0);
#endif /* WITH_XMSS */
}
/* No certificates by default */
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->address_family == -1)
options->address_family = AF_UNSPEC;
if (options->listen_addrs == NULL)
add_listen_addr(options, NULL, NULL, 0);
if (options->pid_file == NULL)
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
if (options->login_grace_time == -1)
options->login_grace_time = 120;
if (options->permit_root_login == PERMIT_NOT_SET)
options->permit_root_login = PERMIT_NO_PASSWD;
if (options->ignore_rhosts == -1)
options->ignore_rhosts = 1;
if (options->ignore_user_known_hosts == -1)
options->ignore_user_known_hosts = 0;
if (options->print_motd == -1)
options->print_motd = 1;
if (options->print_lastlog == -1)
options->print_lastlog = 1;
if (options->x11_forwarding == -1)
options->x11_forwarding = 0;
if (options->x11_display_offset == -1)
options->x11_display_offset = 10;
if (options->x11_use_localhost == -1)
options->x11_use_localhost = 1;
if (options->xauth_location == NULL)
options->xauth_location = xstrdup(_PATH_XAUTH);
if (options->permit_tty == -1)
options->permit_tty = 1;
if (options->permit_user_rc == -1)
options->permit_user_rc = 1;
if (options->strict_modes == -1)
options->strict_modes = 1;
if (options->tcp_keep_alive == -1)
options->tcp_keep_alive = 1;
if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
options->log_facility = SYSLOG_FACILITY_AUTH;
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
if (options->hostbased_authentication == -1)
options->hostbased_authentication = 0;
if (options->hostbased_uses_name_from_packet_only == -1)
options->hostbased_uses_name_from_packet_only = 0;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
if (options->kerberos_authentication == -1)
options->kerberos_authentication = 0;
if (options->kerberos_or_local_passwd == -1)
options->kerberos_or_local_passwd = 1;
if (options->kerberos_ticket_cleanup == -1)
options->kerberos_ticket_cleanup = 1;
if (options->kerberos_get_afs_token == -1)
options->kerberos_get_afs_token = 0;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_cleanup_creds == -1)
options->gss_cleanup_creds = 1;
if (options->gss_strict_acceptor == -1)
options->gss_strict_acceptor = 1;
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
options->kbd_interactive_authentication = 0;
if (options->challenge_response_authentication == -1)
options->challenge_response_authentication = 1;
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
if (options->permit_user_env == -1) {
options->permit_user_env = 0;
options->permit_user_env_whitelist = NULL;
}
if (options->compression == -1)
options->compression = COMP_DELAYED;
if (options->rekey_limit == -1)
options->rekey_limit = 0;
if (options->rekey_interval == -1)
options->rekey_interval = 0;
if (options->allow_tcp_forwarding == -1)
options->allow_tcp_forwarding = FORWARD_ALLOW;
if (options->allow_streamlocal_forwarding == -1)
options->allow_streamlocal_forwarding = FORWARD_ALLOW;
if (options->allow_agent_forwarding == -1)
options->allow_agent_forwarding = 1;
if (options->fwd_opts.gateway_ports == -1)
options->fwd_opts.gateway_ports = 0;
if (options->max_startups == -1)
options->max_startups = 100;
if (options->max_startups_rate == -1)
options->max_startups_rate = 30; /* 30% */
if (options->max_startups_begin == -1)
options->max_startups_begin = 10;
if (options->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
options->max_sessions = DEFAULT_SESSIONS_MAX;
if (options->use_dns == -1)
options->use_dns = 0;
if (options->client_alive_interval == -1)
options->client_alive_interval = 0;
if (options->client_alive_count_max == -1)
options->client_alive_count_max = 3;
if (options->num_authkeys_files == 0) {
array_append("[default]", 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS);
array_append("[default]", 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS2);
}
if (options->permit_tun == -1)
options->permit_tun = SSH_TUNMODE_NO;
if (options->ip_qos_interactive == -1)
options->ip_qos_interactive = IPTOS_DSCP_AF21;
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_DSCP_CS1;
if (options->version_addendum == NULL)
options->version_addendum = xstrdup("");
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
if (options->disable_forwarding == -1)
options->disable_forwarding = 0;
if (options->expose_userauth_info == -1)
options->expose_userauth_info = 0;
assemble_algorithms(options);
/* Turn privilege separation and sandboxing on by default */
if (use_privsep == -1)
use_privsep = PRIVSEP_ON;
#define CLEAR_ON_NONE(v) \
do { \
if (option_clear_or_none(v)) { \
free(v); \
v = NULL; \
} \
} while(0)
CLEAR_ON_NONE(options->pid_file);
CLEAR_ON_NONE(options->xauth_location);
CLEAR_ON_NONE(options->banner);
CLEAR_ON_NONE(options->trusted_user_ca_keys);
CLEAR_ON_NONE(options->revoked_keys_file);
CLEAR_ON_NONE(options->authorized_principals_file);
CLEAR_ON_NONE(options->adm_forced_command);
CLEAR_ON_NONE(options->chroot_directory);
CLEAR_ON_NONE(options->routing_domain);
for (i = 0; i < options->num_host_key_files; i++)
CLEAR_ON_NONE(options->host_key_files[i]);
for (i = 0; i < options->num_host_cert_files; i++)
CLEAR_ON_NONE(options->host_cert_files[i]);
#undef CLEAR_ON_NONE
/* Similar handling for AuthenticationMethods=any */
if (options->num_auth_methods == 1 &&
strcmp(options->auth_methods[0], "any") == 0) {
free(options->auth_methods[0]);
options->auth_methods[0] = NULL;
options->num_auth_methods = 0;
}
#ifndef HAVE_MMAP
if (use_privsep && options->compression == 1) {
error("This platform does not support both privilege "
"separation and compression");
error("Compression disabled");
options->compression = 0;
}
#endif
-
}
/* Keyword tokens. */
typedef enum {
sBadOption, /* == unknown option */
/* Portable-specific options */
sUsePAM,
/* Standard Options */
sPort, sHostKeyFile, sLoginGraceTime,
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
sKerberosGetAFSToken, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
sAcceptEnv, sSetEnv, sPermitTunnel,
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
sExposeAuthInfo, sRDomain,
sDeprecated, sIgnore, sUnsupported
} ServerOpCodes;
#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
/* Textual representation of the tokens. */
static struct {
const char *name;
ServerOpCodes opcode;
u_int flags;
} keywords[] = {
/* Portable-specific options */
#ifdef USE_PAM
{ "usepam", sUsePAM, SSHCFG_GLOBAL },
#else
{ "usepam", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
/* Standard Options */
{ "port", sPort, SSHCFG_GLOBAL },
{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
{ "pidfile", sPidFile, SSHCFG_GLOBAL },
{ "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
{ "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
{ "loglevel", sLogLevel, SSHCFG_ALL },
{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
{ "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
{ "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL },
{ "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
{ "rsaauthentication", sDeprecated, SSHCFG_ALL },
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
{ "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
#ifdef KRB5
{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
#ifdef USE_AFS
{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
#else
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
#ifdef GSSAPI
{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
#else
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
{ "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
#endif
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
{ "skeyauthentication", sDeprecated, SSHCFG_GLOBAL },
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
#ifdef DISABLE_LASTLOG
{ "printlastlog", sUnsupported, SSHCFG_GLOBAL },
#else
{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
#endif
{ "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
{ "uselogin", sDeprecated, SSHCFG_GLOBAL },
{ "compression", sCompression, SSHCFG_GLOBAL },
{ "rekeylimit", sRekeyLimit, SSHCFG_ALL },
{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
{ "allowusers", sAllowUsers, SSHCFG_ALL },
{ "denyusers", sDenyUsers, SSHCFG_ALL },
{ "allowgroups", sAllowGroups, SSHCFG_ALL },
{ "denygroups", sDenyGroups, SSHCFG_ALL },
{ "ciphers", sCiphers, SSHCFG_GLOBAL },
{ "macs", sMacs, SSHCFG_GLOBAL },
{ "protocol", sIgnore, SSHCFG_GLOBAL },
{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
{ "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL },
{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL },
{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
{ "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
{ "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL},
{ "acceptenv", sAcceptEnv, SSHCFG_ALL },
{ "setenv", sSetEnv, SSHCFG_ALL },
{ "permittunnel", sPermitTunnel, SSHCFG_ALL },
{ "permittty", sPermitTTY, SSHCFG_ALL },
{ "permituserrc", sPermitUserRC, SSHCFG_ALL },
{ "match", sMatch, SSHCFG_ALL },
{ "permitopen", sPermitOpen, SSHCFG_ALL },
{ "permitlisten", sPermitListen, SSHCFG_ALL },
{ "forcecommand", sForceCommand, SSHCFG_ALL },
{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
{ "ipqos", sIPQoS, SSHCFG_ALL },
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
{ "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL },
{ "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL },
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
{ "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
{ "disableforwarding", sDisableForwarding, SSHCFG_ALL },
{ "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
{ "rdomain", sRDomain, SSHCFG_ALL },
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
static struct {
int val;
char *text;
} tunmode_desc[] = {
{ SSH_TUNMODE_NO, "no" },
{ SSH_TUNMODE_POINTOPOINT, "point-to-point" },
{ SSH_TUNMODE_ETHERNET, "ethernet" },
{ SSH_TUNMODE_YES, "yes" },
{ -1, NULL }
};
/* Returns an opcode name from its number */
static const char *
lookup_opcode_name(ServerOpCodes code)
{
u_int i;
for (i = 0; keywords[i].name != NULL; i++)
if (keywords[i].opcode == code)
return(keywords[i].name);
return "UNKNOWN";
}
/*
* Returns the number of the token pointed to by cp or sBadOption.
*/
static ServerOpCodes
parse_token(const char *cp, const char *filename,
int linenum, u_int *flags)
{
u_int i;
for (i = 0; keywords[i].name; i++)
if (strcasecmp(cp, keywords[i].name) == 0) {
*flags = keywords[i].flags;
return keywords[i].opcode;
}
error("%s: line %d: Bad configuration option: %s",
filename, linenum, cp);
return sBadOption;
}
char *
derelativise_path(const char *path)
{
char *expanded, *ret, cwd[PATH_MAX];
if (strcasecmp(path, "none") == 0)
return xstrdup("none");
expanded = tilde_expand_filename(path, getuid());
- if (*expanded == '/')
+ if (path_absolute(expanded))
return expanded;
if (getcwd(cwd, sizeof(cwd)) == NULL)
fatal("%s: getcwd: %s", __func__, strerror(errno));
xasprintf(&ret, "%s/%s", cwd, expanded);
free(expanded);
return ret;
}
static void
add_listen_addr(ServerOptions *options, const char *addr,
const char *rdomain, int port)
{
u_int i;
if (port > 0)
add_one_listen_addr(options, addr, rdomain, port);
else {
for (i = 0; i < options->num_ports; i++) {
add_one_listen_addr(options, addr, rdomain,
options->ports[i]);
}
}
}
static void
add_one_listen_addr(ServerOptions *options, const char *addr,
const char *rdomain, int port)
{
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr;
u_int i;
/* Find listen_addrs entry for this rdomain */
for (i = 0; i < options->num_listen_addrs; i++) {
if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
break;
if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
continue;
if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
break;
}
if (i >= options->num_listen_addrs) {
/* No entry for this rdomain; allocate one */
if (i >= INT_MAX)
fatal("%s: too many listen addresses", __func__);
options->listen_addrs = xrecallocarray(options->listen_addrs,
options->num_listen_addrs, options->num_listen_addrs + 1,
sizeof(*options->listen_addrs));
i = options->num_listen_addrs++;
if (rdomain != NULL)
options->listen_addrs[i].rdomain = xstrdup(rdomain);
}
/* options->listen_addrs[i] points to the addresses for this rdomain */
memset(&hints, 0, sizeof(hints));
hints.ai_family = options->address_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
fatal("bad addr or host: %s (%s)",
addr ? addr : "<NULL>",
ssh_gai_strerror(gaierr));
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
;
ai->ai_next = options->listen_addrs[i].addrs;
options->listen_addrs[i].addrs = aitop;
}
/* Returns nonzero if the routing domain name is valid */
static int
valid_rdomain(const char *name)
{
#if defined(HAVE_SYS_VALID_RDOMAIN)
return sys_valid_rdomain(name);
#elif defined(__OpenBSD__)
const char *errstr;
long long num;
struct rt_tableinfo info;
int mib[6];
size_t miblen = sizeof(mib);
if (name == NULL)
return 1;
num = strtonum(name, 0, 255, &errstr);
if (errstr != NULL)
return 0;
/* Check whether the table actually exists */
memset(mib, 0, sizeof(mib));
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[4] = NET_RT_TABLE;
mib[5] = (int)num;
if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
return 0;
return 1;
#else /* defined(__OpenBSD__) */
error("Routing domains are not supported on this platform");
return 0;
#endif
}
/*
* Queue a ListenAddress to be processed once we have all of the Ports
* and AddressFamily options.
*/
static void
queue_listen_addr(ServerOptions *options, const char *addr,
const char *rdomain, int port)
{
struct queued_listenaddr *qla;
options->queued_listen_addrs = xrecallocarray(
options->queued_listen_addrs,
options->num_queued_listens, options->num_queued_listens + 1,
sizeof(*options->queued_listen_addrs));
qla = &options->queued_listen_addrs[options->num_queued_listens++];
qla->addr = xstrdup(addr);
qla->port = port;
qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
}
/*
* Process queued (text) ListenAddress entries.
*/
static void
process_queued_listen_addrs(ServerOptions *options)
{
u_int i;
struct queued_listenaddr *qla;
if (options->num_ports == 0)
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
if (options->address_family == -1)
options->address_family = AF_UNSPEC;
for (i = 0; i < options->num_queued_listens; i++) {
qla = &options->queued_listen_addrs[i];
add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
free(qla->addr);
free(qla->rdomain);
}
free(options->queued_listen_addrs);
options->queued_listen_addrs = NULL;
options->num_queued_listens = 0;
}
/*
* Inform channels layer of permitopen options for a single forwarding
* direction (local/remote).
*/
static void
process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode,
char **opens, u_int num_opens)
{
u_int i;
int port;
- char *host, *arg, *oarg;
+ char *host, *arg, *oarg, ch;
int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE;
const char *what = lookup_opcode_name(opcode);
channel_clear_permission(ssh, FORWARD_ADM, where);
if (num_opens == 0)
return; /* permit any */
/* handle keywords: "any" / "none" */
if (num_opens == 1 && strcmp(opens[0], "any") == 0)
return;
if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
channel_disable_admin(ssh, where);
return;
}
/* Otherwise treat it as a list of permitted host:port */
for (i = 0; i < num_opens; i++) {
oarg = arg = xstrdup(opens[i]);
- host = hpdelim(&arg);
- if (host == NULL)
+ ch = '\0';
+ host = hpdelim2(&arg, &ch);
+ if (host == NULL || ch == '/')
fatal("%s: missing host in %s", __func__, what);
host = cleanhostname(host);
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
fatal("%s: bad port number in %s", __func__, what);
/* Send it to channels layer */
channel_add_permission(ssh, FORWARD_ADM,
where, host, port);
free(oarg);
}
}
/*
* Inform channels layer of permitopen options from configuration.
*/
void
process_permitopen(struct ssh *ssh, ServerOptions *options)
{
process_permitopen_list(ssh, sPermitOpen,
options->permitted_opens, options->num_permitted_opens);
process_permitopen_list(ssh, sPermitListen,
options->permitted_listens,
options->num_permitted_listens);
}
struct connection_info *
-get_connection_info(int populate, int use_dns)
+get_connection_info(struct ssh *ssh, int populate, int use_dns)
{
- struct ssh *ssh = active_state; /* XXX */
static struct connection_info ci;
- if (!populate)
+ if (ssh == NULL || !populate)
return &ci;
ci.host = auth_get_canonical_hostname(ssh, use_dns);
ci.address = ssh_remote_ipaddr(ssh);
ci.laddress = ssh_local_ipaddr(ssh);
ci.lport = ssh_local_port(ssh);
ci.rdomain = ssh_packet_rdomain_in(ssh);
return &ci;
}
/*
* The strategy for the Match blocks is that the config file is parsed twice.
*
* The first time is at startup. activep is initialized to 1 and the
* directives in the global context are processed and acted on. Hitting a
* Match directive unsets activep and the directives inside the block are
* checked for syntax only.
*
* The second time is after a connection has been established but before
* authentication. activep is initialized to 2 and global config directives
* are ignored since they have already been processed. If the criteria in a
* Match block is met, activep is set and the subsequent directives
* processed and actioned until EOF or another Match block unsets it. Any
* options set are copied into the main server config.
*
* Potential additions/improvements:
* - Add Match support for pre-kex directives, eg. Ciphers.
*
* - Add a Tag directive (idea from David Leonard) ala pf, eg:
* Match Address 192.168.0.*
* Tag trusted
* Match Group wheel
* Tag trusted
* Match Tag trusted
* AllowTcpForwarding yes
* GatewayPorts clientspecified
* [...]
*
* - Add a PermittedChannelRequests directive
* Match Group shell
* PermittedChannelRequests session,forwarded-tcpip
*/
static int
match_cfg_line_group(const char *grps, int line, const char *user)
{
int result = 0;
struct passwd *pw;
if (user == NULL)
goto out;
if ((pw = getpwnam(user)) == NULL) {
debug("Can't match group at line %d because user %.100s does "
"not exist", line, user);
} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
debug("Can't Match group because user %.100s not in any group "
"at line %d", user, line);
} else if (ga_match_pattern_list(grps) != 1) {
debug("user %.100s does not match group list %.100s at line %d",
user, grps, line);
} else {
debug("user %.100s matched group list %.100s at line %d", user,
grps, line);
result = 1;
}
out:
ga_free();
return result;
}
static void
match_test_missing_fatal(const char *criteria, const char *attrib)
{
fatal("'Match %s' in configuration but '%s' not in connection "
"test specification.", criteria, attrib);
}
/*
* All of the attributes on a single Match line are ANDed together, so we need
* to check every attribute and set the result to zero if any attribute does
* not match.
*/
static int
match_cfg_line(char **condition, int line, struct connection_info *ci)
{
int result = 1, attributes = 0, port;
char *arg, *attrib, *cp = *condition;
if (ci == NULL)
debug3("checking syntax for 'Match %s'", cp);
else
debug3("checking match for '%s' user %s host %s addr %s "
"laddr %s lport %d", cp, ci->user ? ci->user : "(null)",
ci->host ? ci->host : "(null)",
ci->address ? ci->address : "(null)",
ci->laddress ? ci->laddress : "(null)", ci->lport);
while ((attrib = strdelim(&cp)) && *attrib != '\0') {
attributes++;
if (strcasecmp(attrib, "all") == 0) {
if (attributes != 1 ||
((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
error("'all' cannot be combined with other "
"Match attributes");
return -1;
}
*condition = cp;
return 1;
}
if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
error("Missing Match criteria for %s", attrib);
return -1;
}
if (strcasecmp(attrib, "user") == 0) {
if (ci == NULL) {
result = 0;
continue;
}
if (ci->user == NULL)
match_test_missing_fatal("User", "user");
- if (match_pattern_list(ci->user, arg, 0) != 1)
+ if (match_usergroup_pattern_list(ci->user, arg) != 1)
result = 0;
else
debug("user %.100s matched 'User %.100s' at "
"line %d", ci->user, arg, line);
} else if (strcasecmp(attrib, "group") == 0) {
if (ci == NULL) {
result = 0;
continue;
}
if (ci->user == NULL)
match_test_missing_fatal("Group", "user");
switch (match_cfg_line_group(arg, line, ci->user)) {
case -1:
return -1;
case 0:
result = 0;
}
} else if (strcasecmp(attrib, "host") == 0) {
if (ci == NULL) {
result = 0;
continue;
}
if (ci->host == NULL)
match_test_missing_fatal("Host", "host");
if (match_hostname(ci->host, arg) != 1)
result = 0;
else
debug("connection from %.100s matched 'Host "
"%.100s' at line %d", ci->host, arg, line);
} else if (strcasecmp(attrib, "address") == 0) {
if (ci == NULL) {
result = 0;
continue;
}
if (ci->address == NULL)
match_test_missing_fatal("Address", "addr");
switch (addr_match_list(ci->address, arg)) {
case 1:
debug("connection from %.100s matched 'Address "
"%.100s' at line %d", ci->address, arg, line);
break;
case 0:
case -1:
result = 0;
break;
case -2:
return -1;
}
} else if (strcasecmp(attrib, "localaddress") == 0){
if (ci == NULL) {
result = 0;
continue;
}
if (ci->laddress == NULL)
match_test_missing_fatal("LocalAddress",
"laddr");
switch (addr_match_list(ci->laddress, arg)) {
case 1:
debug("connection from %.100s matched "
"'LocalAddress %.100s' at line %d",
ci->laddress, arg, line);
break;
case 0:
case -1:
result = 0;
break;
case -2:
return -1;
}
} else if (strcasecmp(attrib, "localport") == 0) {
if ((port = a2port(arg)) == -1) {
error("Invalid LocalPort '%s' on Match line",
arg);
return -1;
}
if (ci == NULL) {
result = 0;
continue;
}
if (ci->lport == 0)
match_test_missing_fatal("LocalPort", "lport");
/* TODO support port lists */
if (port == ci->lport)
debug("connection from %.100s matched "
"'LocalPort %d' at line %d",
ci->laddress, port, line);
else
result = 0;
} else if (strcasecmp(attrib, "rdomain") == 0) {
if (ci == NULL || ci->rdomain == NULL) {
result = 0;
continue;
}
if (match_pattern_list(ci->rdomain, arg, 0) != 1)
result = 0;
else
debug("user %.100s matched 'RDomain %.100s' at "
"line %d", ci->rdomain, arg, line);
} else {
error("Unsupported Match attribute %s", attrib);
return -1;
}
}
if (attributes == 0) {
error("One or more attributes required for Match");
return -1;
}
if (ci != NULL)
debug3("match %sfound", result ? "" : "not ");
*condition = cp;
return result;
}
#define WHITESPACE " \t\r\n"
/* Multistate option parsing */
struct multistate {
char *key;
int value;
};
static const struct multistate multistate_flag[] = {
{ "yes", 1 },
{ "no", 0 },
{ NULL, -1 }
};
static const struct multistate multistate_addressfamily[] = {
{ "inet", AF_INET },
{ "inet6", AF_INET6 },
{ "any", AF_UNSPEC },
{ NULL, -1 }
};
static const struct multistate multistate_permitrootlogin[] = {
{ "without-password", PERMIT_NO_PASSWD },
{ "prohibit-password", PERMIT_NO_PASSWD },
{ "forced-commands-only", PERMIT_FORCED_ONLY },
{ "yes", PERMIT_YES },
{ "no", PERMIT_NO },
{ NULL, -1 }
};
static const struct multistate multistate_compression[] = {
{ "yes", COMP_DELAYED },
{ "delayed", COMP_DELAYED },
{ "no", COMP_NONE },
{ NULL, -1 }
};
static const struct multistate multistate_gatewayports[] = {
{ "clientspecified", 2 },
{ "yes", 1 },
{ "no", 0 },
{ NULL, -1 }
};
static const struct multistate multistate_tcpfwd[] = {
{ "yes", FORWARD_ALLOW },
{ "all", FORWARD_ALLOW },
{ "no", FORWARD_DENY },
{ "remote", FORWARD_REMOTE },
{ "local", FORWARD_LOCAL },
{ NULL, -1 }
};
int
process_server_config_line(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep,
struct connection_info *connectinfo)
{
- char *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
+ char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
int cmdline = 0, *intptr, value, value2, n, port;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
ServerOpCodes opcode;
u_int i, *uintptr, uvalue, flags = 0;
size_t len;
long long val64;
const struct multistate *multistate_ptr;
const char *errstr;
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
return 0;
for (len--; len > 0; len--) {
if (strchr(WHITESPACE "\f", line[len]) == NULL)
break;
line[len] = '\0';
}
cp = line;
if ((arg = strdelim(&cp)) == NULL)
return 0;
/* Ignore leading whitespace */
if (*arg == '\0')
arg = strdelim(&cp);
if (!arg || !*arg || *arg == '#')
return 0;
intptr = NULL;
charptr = NULL;
opcode = parse_token(arg, filename, linenum, &flags);
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
activep = &cmdline;
}
if (*activep && opcode != sMatch)
debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
if (connectinfo == NULL) {
fatal("%s line %d: Directive '%s' is not allowed "
"within a Match block", filename, linenum, arg);
} else { /* this is a directive we have already processed */
while (arg)
arg = strdelim(&cp);
return 0;
}
}
switch (opcode) {
/* Portable-specific options */
case sUsePAM:
intptr = &options->use_pam;
goto parse_flag;
/* Standard Options */
case sBadOption:
return -1;
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
if (options->ports_from_cmdline)
return 0;
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.",
filename, linenum);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.",
filename, linenum);
options->ports[options->num_ports++] = a2port(arg);
if (options->ports[options->num_ports-1] <= 0)
fatal("%s line %d: Badly formatted port number.",
filename, linenum);
break;
case sLoginGraceTime:
intptr = &options->login_grace_time;
parse_time:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
filename, linenum);
if ((value = convtime(arg)) == -1)
fatal("%s line %d: invalid time value.",
filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sListenAddress:
arg = strdelim(&cp);
if (arg == NULL || *arg == '\0')
fatal("%s line %d: missing address",
filename, linenum);
/* check for bare IPv6 address: no "[]" and 2 or more ":" */
if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
&& strchr(p+1, ':') != NULL) {
port = 0;
p = arg;
} else {
- p = hpdelim(&arg);
- if (p == NULL)
+ arg2 = NULL;
+ ch = '\0';
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/')
fatal("%s line %d: bad address:port usage",
filename, linenum);
p = cleanhostname(p);
if (arg == NULL)
port = 0;
else if ((port = a2port(arg)) <= 0)
fatal("%s line %d: bad port number",
filename, linenum);
}
/* Optional routing table */
arg2 = NULL;
if ((arg = strdelim(&cp)) != NULL) {
if (strcmp(arg, "rdomain") != 0 ||
(arg2 = strdelim(&cp)) == NULL)
fatal("%s line %d: bad ListenAddress syntax",
filename, linenum);
if (!valid_rdomain(arg2))
fatal("%s line %d: bad routing domain",
filename, linenum);
}
queue_listen_addr(options, p, arg2, port);
break;
case sAddressFamily:
intptr = &options->address_family;
multistate_ptr = multistate_addressfamily;
parse_multistate:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing argument.",
filename, linenum);
value = -1;
for (i = 0; multistate_ptr[i].key != NULL; i++) {
if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
value = multistate_ptr[i].value;
break;
}
}
if (value == -1)
fatal("%s line %d: unsupported option \"%s\".",
filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sHostKeyFile:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
- if (*activep)
- servconf_add_hostkey(filename, linenum, options, arg);
+ if (*activep) {
+ servconf_add_hostkey(filename, linenum,
+ options, arg, 1);
+ }
break;
case sHostKeyAgent:
charptr = &options->host_key_agent;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing socket name.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ?
xstrdup(arg) : derelativise_path(arg);
break;
case sHostCertificate:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep)
servconf_add_hostcert(filename, linenum, options, arg);
break;
case sPidFile:
charptr = &options->pid_file;
parse_filename:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep && *charptr == NULL) {
*charptr = derelativise_path(arg);
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sPermitRootLogin:
intptr = &options->permit_root_login;
multistate_ptr = multistate_permitrootlogin;
goto parse_multistate;
case sIgnoreRhosts:
intptr = &options->ignore_rhosts;
parse_flag:
multistate_ptr = multistate_flag;
goto parse_multistate;
case sIgnoreUserKnownHosts:
intptr = &options->ignore_user_known_hosts;
goto parse_flag;
case sHostbasedAuthentication:
intptr = &options->hostbased_authentication;
goto parse_flag;
case sHostbasedUsesNameFromPacketOnly:
intptr = &options->hostbased_uses_name_from_packet_only;
goto parse_flag;
case sHostbasedAcceptedKeyTypes:
charptr = &options->hostbased_key_types;
parse_keytypes:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (*arg != '-' &&
!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
fatal("%s line %d: Bad key types '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sHostKeyAlgorithms:
charptr = &options->hostkeyalgorithms;
goto parse_keytypes;
case sCASignatureAlgorithms:
charptr = &options->ca_sign_algorithms;
goto parse_keytypes;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
case sPubkeyAcceptedKeyTypes:
charptr = &options->pubkey_key_types;
goto parse_keytypes;
case sKerberosAuthentication:
intptr = &options->kerberos_authentication;
goto parse_flag;
case sKerberosOrLocalPasswd:
intptr = &options->kerberos_or_local_passwd;
goto parse_flag;
case sKerberosTicketCleanup:
intptr = &options->kerberos_ticket_cleanup;
goto parse_flag;
case sKerberosGetAFSToken:
intptr = &options->kerberos_get_afs_token;
goto parse_flag;
case sGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
case sGssCleanupCreds:
intptr = &options->gss_cleanup_creds;
goto parse_flag;
case sGssStrictAcceptor:
intptr = &options->gss_strict_acceptor;
goto parse_flag;
case sPasswordAuthentication:
intptr = &options->password_authentication;
goto parse_flag;
case sKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
case sChallengeResponseAuthentication:
intptr = &options->challenge_response_authentication;
goto parse_flag;
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
case sPrintLastLog:
intptr = &options->print_lastlog;
goto parse_flag;
case sX11Forwarding:
intptr = &options->x11_forwarding;
goto parse_flag;
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
parse_int:
arg = strdelim(&cp);
if ((errstr = atoi_err(arg, &value)) != NULL)
fatal("%s line %d: integer value %s.",
filename, linenum, errstr);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sX11UseLocalhost:
intptr = &options->x11_use_localhost;
goto parse_flag;
case sXAuthLocation:
charptr = &options->xauth_location;
goto parse_filename;
case sPermitTTY:
intptr = &options->permit_tty;
goto parse_flag;
case sPermitUserRC:
intptr = &options->permit_user_rc;
goto parse_flag;
case sStrictModes:
intptr = &options->strict_modes;
goto parse_flag;
case sTCPKeepAlive:
intptr = &options->tcp_keep_alive;
goto parse_flag;
case sEmptyPasswd:
intptr = &options->permit_empty_passwd;
goto parse_flag;
case sPermitUserEnvironment:
intptr = &options->permit_user_env;
charptr = &options->permit_user_env_whitelist;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing argument.",
filename, linenum);
value = 0;
p = NULL;
if (strcmp(arg, "yes") == 0)
value = 1;
else if (strcmp(arg, "no") == 0)
value = 0;
else {
/* Pattern-list specified */
value = 1;
p = xstrdup(arg);
}
if (*activep && *intptr == -1) {
*intptr = value;
*charptr = p;
p = NULL;
}
free(p);
break;
case sCompression:
intptr = &options->compression;
multistate_ptr = multistate_compression;
goto parse_multistate;
case sRekeyLimit:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
if (strcmp(arg, "default") == 0) {
val64 = 0;
} else {
if (scan_scaled(arg, &val64) == -1)
fatal("%.200s line %d: Bad number '%s': %s",
filename, linenum, arg, strerror(errno));
if (val64 != 0 && val64 < 16)
fatal("%.200s line %d: RekeyLimit too small",
filename, linenum);
}
if (*activep && options->rekey_limit == -1)
options->rekey_limit = val64;
if (cp != NULL) { /* optional rekey interval present */
if (strcmp(cp, "none") == 0) {
(void)strdelim(&cp); /* discard */
break;
}
intptr = &options->rekey_interval;
goto parse_time;
}
break;
case sGatewayPorts:
intptr = &options->fwd_opts.gateway_ports;
multistate_ptr = multistate_gatewayports;
goto parse_multistate;
case sUseDNS:
intptr = &options->use_dns;
goto parse_flag;
case sLogFacility:
log_facility_ptr = &options->log_facility;
arg = strdelim(&cp);
value = log_facility_number(arg);
if (value == SYSLOG_FACILITY_NOT_SET)
fatal("%.200s line %d: unsupported log facility '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*log_facility_ptr == -1)
*log_facility_ptr = (SyslogFacility) value;
break;
case sLogLevel:
log_level_ptr = &options->log_level;
arg = strdelim(&cp);
value = log_level_number(arg);
if (value == SYSLOG_LEVEL_NOT_SET)
fatal("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
if (*activep && *log_level_ptr == -1)
*log_level_ptr = (LogLevel) value;
break;
case sAllowTcpForwarding:
intptr = &options->allow_tcp_forwarding;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowStreamLocalForwarding:
intptr = &options->allow_streamlocal_forwarding;
multistate_ptr = multistate_tcpfwd;
goto parse_multistate;
case sAllowAgentForwarding:
intptr = &options->allow_agent_forwarding;
goto parse_flag;
case sDisableForwarding:
intptr = &options->disable_forwarding;
goto parse_flag;
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (match_user(NULL, NULL, NULL, arg) == -1)
fatal("%s line %d: invalid AllowUsers pattern: "
"\"%.100s\"", filename, linenum, arg);
if (!*activep)
continue;
array_append(filename, linenum, "AllowUsers",
&options->allow_users, &options->num_allow_users,
arg);
}
break;
case sDenyUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (match_user(NULL, NULL, NULL, arg) == -1)
fatal("%s line %d: invalid DenyUsers pattern: "
"\"%.100s\"", filename, linenum, arg);
if (!*activep)
continue;
array_append(filename, linenum, "DenyUsers",
&options->deny_users, &options->num_deny_users,
arg);
}
break;
case sAllowGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (!*activep)
continue;
array_append(filename, linenum, "AllowGroups",
&options->allow_groups, &options->num_allow_groups,
arg);
}
break;
case sDenyGroups:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (!*activep)
continue;
array_append(filename, linenum, "DenyGroups",
&options->deny_groups, &options->num_deny_groups,
arg);
}
break;
case sCiphers:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (*arg != '-' && !ciphers_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case sMacs:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.", filename, linenum);
if (*arg != '-' && !mac_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->macs == NULL)
options->macs = xstrdup(arg);
break;
case sKexAlgorithms:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
if (*arg != '-' &&
!kex_names_valid(*arg == '+' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
if (options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
case sSubsystem:
if (options->num_subsystems >= MAX_SUBSYSTEMS) {
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem name.",
filename, linenum);
if (!*activep) {
arg = strdelim(&cp);
break;
}
for (i = 0; i < options->num_subsystems; i++)
if (strcmp(arg, options->subsystem_name[i]) == 0)
fatal("%s line %d: Subsystem '%s' already defined.",
filename, linenum, arg);
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
options->subsystem_command[options->num_subsystems] = xstrdup(arg);
/* Collect arguments (separate to executable) */
p = xstrdup(arg);
len = strlen(p) + 1;
while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
len += 1 + strlen(arg);
p = xreallocarray(p, 1, len);
strlcat(p, " ", len);
strlcat(p, arg, len);
}
options->subsystem_args[options->num_subsystems] = p;
options->num_subsystems++;
break;
case sMaxStartups:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing MaxStartups spec.",
filename, linenum);
if ((n = sscanf(arg, "%d:%d:%d",
&options->max_startups_begin,
&options->max_startups_rate,
&options->max_startups)) == 3) {
if (options->max_startups_begin >
options->max_startups ||
options->max_startups_rate > 100 ||
options->max_startups_rate < 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
} else if (n != 1)
fatal("%s line %d: Illegal MaxStartups spec.",
filename, linenum);
else
options->max_startups = options->max_startups_begin;
break;
case sMaxAuthTries:
intptr = &options->max_authtries;
goto parse_int;
case sMaxSessions:
intptr = &options->max_sessions;
goto parse_int;
case sBanner:
charptr = &options->banner;
goto parse_filename;
/*
* These options can contain %X options expanded at
* connect time, so that you can specify paths like:
*
* AuthorizedKeysFile /etc/ssh_keys/%u
*/
case sAuthorizedKeysFile:
if (*activep && options->num_authkeys_files == 0) {
while ((arg = strdelim(&cp)) && *arg != '\0') {
arg = tilde_expand_filename(arg, getuid());
array_append(filename, linenum,
"AuthorizedKeysFile",
&options->authorized_keys_files,
&options->num_authkeys_files, arg);
free(arg);
}
}
return 0;
case sAuthorizedPrincipalsFile:
charptr = &options->authorized_principals_file;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep && *charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
if (intptr != NULL)
*intptr = *intptr + 1;
}
break;
case sClientAliveInterval:
intptr = &options->client_alive_interval;
goto parse_time;
case sClientAliveCountMax:
intptr = &options->client_alive_count_max;
goto parse_int;
case sAcceptEnv:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (strchr(arg, '=') != NULL)
fatal("%s line %d: Invalid environment name.",
filename, linenum);
if (!*activep)
continue;
array_append(filename, linenum, "AcceptEnv",
&options->accept_env, &options->num_accept_env,
arg);
}
break;
case sSetEnv:
uvalue = options->num_setenv;
while ((arg = strdelimw(&cp)) && *arg != '\0') {
if (strchr(arg, '=') == NULL)
fatal("%s line %d: Invalid environment.",
filename, linenum);
if (!*activep || uvalue != 0)
continue;
array_append(filename, linenum, "SetEnv",
&options->setenv, &options->num_setenv, arg);
}
break;
case sPermitTunnel:
intptr = &options->permit_tun;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing yes/point-to-point/"
"ethernet/no argument.", filename, linenum);
value = -1;
for (i = 0; tunmode_desc[i].val != -1; i++)
if (strcmp(tunmode_desc[i].text, arg) == 0) {
value = tunmode_desc[i].val;
break;
}
if (value == -1)
fatal("%s line %d: Bad yes/point-to-point/ethernet/"
"no argument: %s", filename, linenum, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
case sMatch:
if (cmdline)
fatal("Match directive not supported as a command-line "
"option");
value = match_cfg_line(&cp, linenum, connectinfo);
if (value < 0)
fatal("%s line %d: Bad Match condition", filename,
linenum);
*activep = value;
break;
case sPermitListen:
case sPermitOpen:
if (opcode == sPermitListen) {
uintptr = &options->num_permitted_listens;
chararrayptr = &options->permitted_listens;
} else {
uintptr = &options->num_permitted_opens;
chararrayptr = &options->permitted_opens;
}
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing %s specification",
filename, linenum, lookup_opcode_name(opcode));
uvalue = *uintptr; /* modified later */
if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
if (*activep && uvalue == 0) {
*uintptr = 1;
*chararrayptr = xcalloc(1,
sizeof(**chararrayptr));
(*chararrayptr)[0] = xstrdup(arg);
}
break;
}
for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
if (opcode == sPermitListen &&
strchr(arg, ':') == NULL) {
/*
* Allow bare port number for PermitListen
* to indicate a wildcard listen host.
*/
xasprintf(&arg2, "*:%s", arg);
} else {
arg2 = xstrdup(arg);
- p = hpdelim(&arg);
- if (p == NULL) {
+ ch = '\0';
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/') {
fatal("%s line %d: missing host in %s",
filename, linenum,
lookup_opcode_name(opcode));
}
p = cleanhostname(p);
}
if (arg == NULL ||
((port = permitopen_port(arg)) < 0)) {
fatal("%s line %d: bad port number in %s",
filename, linenum,
lookup_opcode_name(opcode));
}
if (*activep && uvalue == 0) {
array_append(filename, linenum,
lookup_opcode_name(opcode),
chararrayptr, uintptr, arg2);
}
free(arg2);
}
break;
case sForceCommand:
if (cp == NULL || *cp == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep && options->adm_forced_command == NULL)
options->adm_forced_command = xstrdup(cp + len);
return 0;
case sChrootDirectory:
charptr = &options->chroot_directory;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sTrustedUserCAKeys:
charptr = &options->trusted_user_ca_keys;
goto parse_filename;
case sRevokedKeys:
charptr = &options->revoked_keys_file;
goto parse_filename;
case sIPQoS:
arg = strdelim(&cp);
if ((value = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
arg = strdelim(&cp);
if (arg == NULL)
value2 = value;
else if ((value2 = parse_ipqos(arg)) == -1)
fatal("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
if (*activep) {
options->ip_qos_interactive = value;
options->ip_qos_bulk = value2;
}
break;
case sVersionAddendum:
if (cp == NULL || *cp == '\0')
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep && options->version_addendum == NULL) {
if (strcasecmp(cp + len, "none") == 0)
options->version_addendum = xstrdup("");
else if (strchr(cp + len, '\r') != NULL)
fatal("%.200s line %d: Invalid argument",
filename, linenum);
else
options->version_addendum = xstrdup(cp + len);
}
return 0;
case sAuthorizedKeysCommand:
if (cp == NULL)
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep && options->authorized_keys_command == NULL) {
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
fatal("%.200s line %d: AuthorizedKeysCommand "
"must be an absolute path",
filename, linenum);
options->authorized_keys_command = xstrdup(cp + len);
}
return 0;
case sAuthorizedKeysCommandUser:
charptr = &options->authorized_keys_command_user;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing AuthorizedKeysCommandUser "
"argument.", filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sAuthorizedPrincipalsCommand:
if (cp == NULL)
fatal("%.200s line %d: Missing argument.", filename,
linenum);
len = strspn(cp, WHITESPACE);
if (*activep &&
options->authorized_principals_command == NULL) {
if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
fatal("%.200s line %d: "
"AuthorizedPrincipalsCommand must be "
"an absolute path", filename, linenum);
options->authorized_principals_command =
xstrdup(cp + len);
}
return 0;
case sAuthorizedPrincipalsCommandUser:
charptr = &options->authorized_principals_command_user;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing "
"AuthorizedPrincipalsCommandUser argument.",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sAuthenticationMethods:
if (options->num_auth_methods == 0) {
value = 0; /* seen "any" pseudo-method */
value2 = 0; /* successfully parsed any method */
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (strcmp(arg, "any") == 0) {
if (options->num_auth_methods > 0) {
fatal("%s line %d: \"any\" "
"must appear alone in "
"AuthenticationMethods",
filename, linenum);
}
value = 1;
} else if (value) {
fatal("%s line %d: \"any\" must appear "
"alone in AuthenticationMethods",
filename, linenum);
} else if (auth2_methods_valid(arg, 0) != 0) {
fatal("%s line %d: invalid "
"authentication method list.",
filename, linenum);
}
value2 = 1;
if (!*activep)
continue;
array_append(filename, linenum,
"AuthenticationMethods",
&options->auth_methods,
&options->num_auth_methods, arg);
}
if (value2 == 0) {
fatal("%s line %d: no AuthenticationMethods "
"specified", filename, linenum);
}
}
return 0;
case sStreamLocalBindMask:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%s line %d: missing StreamLocalBindMask "
"argument.", filename, linenum);
/* Parse mode in octal format */
value = strtol(arg, &p, 8);
if (arg == p || value < 0 || value > 0777)
fatal("%s line %d: Bad mask.", filename, linenum);
if (*activep)
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
case sStreamLocalBindUnlink:
intptr = &options->fwd_opts.streamlocal_bind_unlink;
goto parse_flag;
case sFingerprintHash:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if ((value = ssh_digest_alg_by_name(arg)) == -1)
fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
filename, linenum, arg);
if (*activep)
options->fingerprint_hash = value;
break;
case sExposeAuthInfo:
intptr = &options->expose_userauth_info;
goto parse_flag;
case sRDomain:
charptr = &options->routing_domain;
arg = strdelim(&cp);
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
!valid_rdomain(arg))
fatal("%s line %d: bad routing domain",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sDeprecated:
case sIgnore:
case sUnsupported:
do_log2(opcode == sIgnore ?
SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
"%s line %d: %s option %s", filename, linenum,
opcode == sUnsupported ? "Unsupported" : "Deprecated", arg);
while (arg)
arg = strdelim(&cp);
break;
default:
fatal("%s line %d: Missing handler for opcode %s (%d)",
filename, linenum, arg, opcode);
}
if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
fatal("%s line %d: garbage at end of line; \"%.200s\".",
filename, linenum, arg);
return 0;
}
/* Reads the server configuration file. */
void
load_server_config(const char *filename, struct sshbuf *conf)
{
char *line = NULL, *cp;
size_t linesize = 0;
FILE *f;
int r, lineno = 0;
debug2("%s: filename %s", __func__, filename);
if ((f = fopen(filename, "r")) == NULL) {
perror(filename);
exit(1);
}
sshbuf_reset(conf);
while (getline(&line, &linesize, f) != -1) {
lineno++;
/*
* Trim out comments and strip whitespace
* NB - preserve newlines, they are needed to reproduce
* line numbers later for error messages
*/
if ((cp = strchr(line, '#')) != NULL)
memcpy(cp, "\n", 2);
cp = line + strspn(line, " \t\r");
if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
free(line);
if ((r = sshbuf_put_u8(conf, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
fclose(f);
debug2("%s: done config len = %zu", __func__, sshbuf_len(conf));
}
void
parse_server_match_config(ServerOptions *options,
struct connection_info *connectinfo)
{
ServerOptions mo;
initialize_server_options(&mo);
parse_server_config(&mo, "reprocess config", cfg, connectinfo);
copy_set_server_options(options, &mo, 0);
}
int parse_server_match_testspec(struct connection_info *ci, char *spec)
{
char *p;
while ((p = strsep(&spec, ",")) && *p != '\0') {
if (strncmp(p, "addr=", 5) == 0) {
ci->address = xstrdup(p + 5);
} else if (strncmp(p, "host=", 5) == 0) {
ci->host = xstrdup(p + 5);
} else if (strncmp(p, "user=", 5) == 0) {
ci->user = xstrdup(p + 5);
} else if (strncmp(p, "laddr=", 6) == 0) {
ci->laddress = xstrdup(p + 6);
} else if (strncmp(p, "rdomain=", 8) == 0) {
ci->rdomain = xstrdup(p + 8);
} else if (strncmp(p, "lport=", 6) == 0) {
ci->lport = a2port(p + 6);
if (ci->lport == -1) {
fprintf(stderr, "Invalid port '%s' in test mode"
" specification %s\n", p+6, p);
return -1;
}
} else {
fprintf(stderr, "Invalid test mode specification %s\n",
p);
return -1;
}
}
return 0;
}
/*
* Copy any supported values that are set.
*
* If the preauth flag is set, we do not bother copying the string or
* array values that are not used pre-authentication, because any that we
* do use must be explicitly sent in mm_getpwnamallow().
*/
void
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
{
#define M_CP_INTOPT(n) do {\
if (src->n != -1) \
dst->n = src->n; \
} while (0)
M_CP_INTOPT(password_authentication);
M_CP_INTOPT(gss_authentication);
M_CP_INTOPT(pubkey_authentication);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
M_CP_INTOPT(allow_tcp_forwarding);
M_CP_INTOPT(allow_streamlocal_forwarding);
M_CP_INTOPT(allow_agent_forwarding);
M_CP_INTOPT(disable_forwarding);
M_CP_INTOPT(expose_userauth_info);
M_CP_INTOPT(permit_tun);
M_CP_INTOPT(fwd_opts.gateway_ports);
M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink);
M_CP_INTOPT(x11_display_offset);
M_CP_INTOPT(x11_forwarding);
M_CP_INTOPT(x11_use_localhost);
M_CP_INTOPT(permit_tty);
M_CP_INTOPT(permit_user_rc);
M_CP_INTOPT(max_sessions);
M_CP_INTOPT(max_authtries);
M_CP_INTOPT(client_alive_count_max);
M_CP_INTOPT(client_alive_interval);
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
M_CP_INTOPT(log_level);
/*
* The bind_mask is a mode_t that may be unsigned, so we can't use
* M_CP_INTOPT - it does a signed comparison that causes compiler
* warnings.
*/
if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) {
dst->fwd_opts.streamlocal_bind_mask =
src->fwd_opts.streamlocal_bind_mask;
}
/* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */
#define M_CP_STROPT(n) do {\
if (src->n != NULL && dst->n != src->n) { \
free(dst->n); \
dst->n = src->n; \
} \
} while(0)
#define M_CP_STRARRAYOPT(s, num_s) do {\
u_int i; \
if (src->num_s != 0) { \
for (i = 0; i < dst->num_s; i++) \
free(dst->s[i]); \
free(dst->s); \
dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \
for (i = 0; i < src->num_s; i++) \
dst->s[i] = xstrdup(src->s[i]); \
dst->num_s = src->num_s; \
} \
} while(0)
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
/* Arguments that accept '+...' need to be expanded */
assemble_algorithms(dst);
/*
* The only things that should be below this point are string options
* which are only used after authentication.
*/
if (preauth)
return;
/* These options may be "none" to clear a global setting */
M_CP_STROPT(adm_forced_command);
if (option_clear_or_none(dst->adm_forced_command)) {
free(dst->adm_forced_command);
dst->adm_forced_command = NULL;
}
M_CP_STROPT(chroot_directory);
if (option_clear_or_none(dst->chroot_directory)) {
free(dst->chroot_directory);
dst->chroot_directory = NULL;
}
}
#undef M_CP_INTOPT
#undef M_CP_STROPT
#undef M_CP_STRARRAYOPT
void
parse_server_config(ServerOptions *options, const char *filename,
struct sshbuf *conf, struct connection_info *connectinfo)
{
int active, linenum, bad_options = 0;
char *cp, *obuf, *cbuf;
debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf));
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
active = connectinfo ? 0 : 1;
linenum = 1;
while ((cp = strsep(&cbuf, "\n")) != NULL) {
if (process_server_config_line(options, cp, filename,
linenum++, &active, connectinfo) != 0)
bad_options++;
}
free(obuf);
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);
process_queued_listen_addrs(options);
}
static const char *
fmt_multistate_int(int val, const struct multistate *m)
{
u_int i;
for (i = 0; m[i].key != NULL; i++) {
if (m[i].value == val)
return m[i].key;
}
return "UNKNOWN";
}
static const char *
fmt_intarg(ServerOpCodes code, int val)
{
if (val == -1)
return "unset";
switch (code) {
case sAddressFamily:
return fmt_multistate_int(val, multistate_addressfamily);
case sPermitRootLogin:
return fmt_multistate_int(val, multistate_permitrootlogin);
case sGatewayPorts:
return fmt_multistate_int(val, multistate_gatewayports);
case sCompression:
return fmt_multistate_int(val, multistate_compression);
case sAllowTcpForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sAllowStreamLocalForwarding:
return fmt_multistate_int(val, multistate_tcpfwd);
case sFingerprintHash:
return ssh_digest_alg_name(val);
default:
switch (val) {
case 0:
return "no";
case 1:
return "yes";
default:
return "UNKNOWN";
}
}
}
static void
dump_cfg_int(ServerOpCodes code, int val)
{
printf("%s %d\n", lookup_opcode_name(code), val);
}
static void
dump_cfg_oct(ServerOpCodes code, int val)
{
printf("%s 0%o\n", lookup_opcode_name(code), val);
}
static void
dump_cfg_fmtint(ServerOpCodes code, int val)
{
printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
}
static void
dump_cfg_string(ServerOpCodes code, const char *val)
{
printf("%s %s\n", lookup_opcode_name(code),
val == NULL ? "none" : val);
}
static void
dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
{
u_int i;
for (i = 0; i < count; i++)
printf("%s %s\n", lookup_opcode_name(code), vals[i]);
}
static void
dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
{
u_int i;
if (count <= 0 && code != sAuthenticationMethods)
return;
printf("%s", lookup_opcode_name(code));
for (i = 0; i < count; i++)
printf(" %s", vals[i]);
if (code == sAuthenticationMethods && count == 0)
printf(" any");
printf("\n");
}
static char *
format_listen_addrs(struct listenaddr *la)
{
int r;
struct addrinfo *ai;
char addr[NI_MAXHOST], port[NI_MAXSERV];
char *laddr1 = xstrdup(""), *laddr2 = NULL;
/*
* ListenAddress must be after Port. add_one_listen_addr pushes
* addresses onto a stack, so to maintain ordering we need to
* print these in reverse order.
*/
for (ai = la->addrs; ai; ai = ai->ai_next) {
if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
sizeof(addr), port, sizeof(port),
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
error("getnameinfo: %.100s", ssh_gai_strerror(r));
continue;
}
laddr2 = laddr1;
if (ai->ai_family == AF_INET6) {
xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
addr, port,
la->rdomain == NULL ? "" : " rdomain ",
la->rdomain == NULL ? "" : la->rdomain,
laddr2);
} else {
xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
addr, port,
la->rdomain == NULL ? "" : " rdomain ",
la->rdomain == NULL ? "" : la->rdomain,
laddr2);
}
free(laddr2);
}
return laddr1;
}
void
dump_config(ServerOptions *o)
{
char *s;
u_int i;
/* these are usually at the top of the config */
for (i = 0; i < o->num_ports; i++)
printf("port %d\n", o->ports[i]);
dump_cfg_fmtint(sAddressFamily, o->address_family);
for (i = 0; i < o->num_listen_addrs; i++) {
s = format_listen_addrs(&o->listen_addrs[i]);
printf("%s", s);
free(s);
}
/* integer arguments */
#ifdef USE_PAM
dump_cfg_fmtint(sUsePAM, o->use_pam);
#endif
dump_cfg_int(sLoginGraceTime, o->login_grace_time);
dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
dump_cfg_int(sMaxAuthTries, o->max_authtries);
dump_cfg_int(sMaxSessions, o->max_sessions);
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
/* formatted integer arguments */
dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
o->hostbased_uses_name_from_packet_only);
dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
#ifdef KRB5
dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
# ifdef USE_AFS
dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
# endif
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
o->kbd_interactive_authentication);
dump_cfg_fmtint(sChallengeResponseAuthentication,
o->challenge_response_authentication);
dump_cfg_fmtint(sPrintMotd, o->print_motd);
#ifndef DISABLE_LASTLOG
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
#endif
dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
dump_cfg_fmtint(sPermitTTY, o->permit_tty);
dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc);
dump_cfg_fmtint(sStrictModes, o->strict_modes);
dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding);
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT);
dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
dump_cfg_string(sBanner, o->banner);
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
dump_cfg_string(sAuthorizedPrincipalsFile,
o->authorized_principals_file);
dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0'
? "none" : o->version_addendum);
dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command);
dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user);
dump_cfg_string(sHostKeyAgent, o->host_key_agent);
dump_cfg_string(sKexAlgorithms,
o->kex_algorithms ? o->kex_algorithms : KEX_SERVER_KEX);
dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms ?
o->ca_sign_algorithms : SSH_ALLOWED_CA_SIGALGS);
dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types ?
o->hostbased_key_types : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms ?
o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types ?
o->pubkey_key_types : KEX_DEFAULT_PK_ALG);
dump_cfg_string(sRDomain, o->routing_domain);
/* string arguments requiring a lookup */
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
/* string array arguments */
dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
o->authorized_keys_files);
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
o->host_key_files);
dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
o->host_cert_files);
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv);
dump_cfg_strarray_oneline(sAuthenticationMethods,
o->num_auth_methods, o->auth_methods);
/* other arguments */
for (i = 0; i < o->num_subsystems; i++)
printf("subsystem %s %s\n", o->subsystem_name[i],
o->subsystem_args[i]);
printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
o->max_startups_rate, o->max_startups);
s = NULL;
for (i = 0; tunmode_desc[i].val != -1; i++) {
if (tunmode_desc[i].val == o->permit_tun) {
s = tunmode_desc[i].text;
break;
}
}
dump_cfg_string(sPermitTunnel, s);
printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
printf("%s\n", iptos2str(o->ip_qos_bulk));
printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
o->rekey_interval);
printf("permitopen");
if (o->num_permitted_opens == 0)
printf(" any");
else {
for (i = 0; i < o->num_permitted_opens; i++)
printf(" %s", o->permitted_opens[i]);
}
printf("\n");
printf("permitlisten");
if (o->num_permitted_listens == 0)
printf(" any");
else {
for (i = 0; i < o->num_permitted_listens; i++)
printf(" %s", o->permitted_listens[i]);
}
printf("\n");
if (o->permit_user_env_whitelist == NULL) {
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
} else {
printf("permituserenvironment %s\n",
o->permit_user_env_whitelist);
}
}
diff --git a/servconf.h b/servconf.h
index 0175e00e8be0..54e0a8d8d9b9 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,280 +1,281 @@
-/* $OpenBSD: servconf.h,v 1.137 2018/09/20 03:28:06 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.139 2019/01/19 21:37:48 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Definitions for server configuration data and for the functions reading it.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#ifndef SERVCONF_H
#define SERVCONF_H
#define MAX_PORTS 256 /* Max # ports. */
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
/* permit_root_login */
#define PERMIT_NOT_SET -1
#define PERMIT_NO 0
#define PERMIT_FORCED_ONLY 1
#define PERMIT_NO_PASSWD 2
#define PERMIT_YES 3
/* use_privsep */
#define PRIVSEP_OFF 0
#define PRIVSEP_ON 1
#define PRIVSEP_NOSANDBOX 2
/* PermitOpen */
#define PERMITOPEN_ANY 0
#define PERMITOPEN_NONE -2
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
/* Magic name for internal sftp-server */
#define INTERNAL_SFTP_NAME "internal-sftp"
struct ssh;
struct fwd_perm_list;
/*
* Used to store addresses from ListenAddr directives. These may be
* incomplete, as they may specify addresses that need to be merged
* with any ports requested by ListenPort.
*/
struct queued_listenaddr {
char *addr;
int port; /* <=0 if unspecified */
char *rdomain;
};
/* Resolved listen addresses, grouped by optional routing domain */
struct listenaddr {
char *rdomain;
struct addrinfo *addrs;
};
typedef struct {
u_int num_ports;
u_int ports_from_cmdline;
int ports[MAX_PORTS]; /* Port number to listen on. */
struct queued_listenaddr *queued_listen_addrs;
u_int num_queued_listens;
struct listenaddr *listen_addrs;
u_int num_listen_addrs;
int address_family; /* Address family used by the server. */
char *routing_domain; /* Bind session to routing domain */
char **host_key_files; /* Files containing host keys. */
+ int *host_key_file_userprovided; /* Key was specified by user. */
u_int num_host_key_files; /* Number of files for host keys. */
char **host_cert_files; /* Files containing host certs. */
u_int num_host_cert_files; /* Number of files for host certs. */
char *host_key_agent; /* ssh-agent socket for host keys. */
char *pid_file; /* Where to put our pid */
int login_grace_time; /* Disconnect if no auth in this time
* (sec). */
int permit_root_login; /* PERMIT_*, see above */
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts
* for RhostsRsaAuth */
int print_motd; /* If true, print /etc/motd. */
int print_lastlog; /* If true, print lastlog */
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
int x11_display_offset; /* What DISPLAY number to start
* searching at */
int x11_use_localhost; /* If true, use localhost for fake X11 server. */
char *xauth_location; /* Location of xauth program */
int permit_tty; /* If false, deny pty allocation */
int permit_user_rc; /* If false, deny ~/.ssh/rc execution */
int strict_modes; /* If true, require string home dir modes. */
int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
char *ciphers; /* Supported SSH2 ciphers. */
char *macs; /* Supported SSH2 macs. */
char *kex_algorithms; /* SSH2 kex methods in order of preference. */
struct ForwardOptions fwd_opts; /* forwarding options */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
int hostbased_authentication; /* If true, permit ssh2 hostbased auth */
int hostbased_uses_name_from_packet_only; /* experimental */
char *hostbased_key_types; /* Key types allowed for hostbased */
char *hostkeyalgorithms; /* SSH2 server key types */
char *ca_sign_algorithms; /* Allowed CA signature algorithms */
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
char *pubkey_key_types; /* Key types allowed for public key */
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */
int kerberos_or_local_passwd; /* If true, permit kerberos
* and any other password
* authentication mechanism,
* such as SecurID or
* /etc/passwd */
int kerberos_ticket_cleanup; /* If true, destroy ticket
* file on logout. */
int kerberos_get_afs_token; /* If true, try to get AFS token if
* authenticated with Kerberos. */
int gss_authentication; /* If true, permit GSSAPI authentication */
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
int password_authentication; /* If true, permit password
* authentication. */
int kbd_interactive_authentication; /* If true, permit */
int challenge_response_authentication;
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */
char *permit_user_env_whitelist; /* pattern-list whitelist */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */
int allow_agent_forwarding;
int disable_forwarding;
u_int num_allow_users;
char **allow_users;
u_int num_deny_users;
char **deny_users;
u_int num_allow_groups;
char **allow_groups;
u_int num_deny_groups;
char **deny_groups;
u_int num_subsystems;
char *subsystem_name[MAX_SUBSYSTEMS];
char *subsystem_command[MAX_SUBSYSTEMS];
char *subsystem_args[MAX_SUBSYSTEMS];
u_int num_accept_env;
char **accept_env;
u_int num_setenv;
char **setenv;
int max_startups_begin;
int max_startups_rate;
int max_startups;
int max_authtries;
int max_sessions;
char *banner; /* SSH-2 banner message */
int use_dns;
int client_alive_interval; /*
* poke the client this often to
* see if it's still there
*/
int client_alive_count_max; /*
* If the client is unresponsive
* for this many intervals above,
* disconnect the session
*/
u_int num_authkeys_files; /* Files containing public keys */
char **authorized_keys_files;
char *adm_forced_command;
int use_pam; /* Enable auth via PAM */
int permit_tun;
char **permitted_opens; /* May also be one of PERMITOPEN_* */
u_int num_permitted_opens;
char **permitted_listens; /* May also be one of PERMITOPEN_* */
u_int num_permitted_listens;
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
char *authorized_keys_command;
char *authorized_keys_command_user;
char *authorized_principals_file;
char *authorized_principals_command;
char *authorized_principals_command_user;
int64_t rekey_limit;
int rekey_interval;
char *version_addendum; /* Appended to SSH banner */
u_int num_auth_methods;
char **auth_methods;
int fingerprint_hash;
int expose_userauth_info;
u_int64_t timing_secret;
} ServerOptions;
/* Information about the incoming connection as used by Match */
struct connection_info {
const char *user;
const char *host; /* possibly resolved hostname */
const char *address; /* remote address */
const char *laddress; /* local address */
int lport; /* local port */
const char *rdomain; /* routing domain if available */
};
/*
* These are string config options that must be copied between the
* Match sub-config and the main config, and must be sent from the
* privsep slave to the privsep master. We use a macro to ensure all
* the options are copied and the copies are done in the correct order.
*
* NB. an option must appear in servconf.c:copy_set_server_options() or
* COPY_MATCH_STRING_OPTS here but never both.
*/
#define COPY_MATCH_STRING_OPTS() do { \
M_CP_STROPT(banner); \
M_CP_STROPT(trusted_user_ca_keys); \
M_CP_STROPT(revoked_keys_file); \
M_CP_STROPT(authorized_keys_command); \
M_CP_STROPT(authorized_keys_command_user); \
M_CP_STROPT(authorized_principals_file); \
M_CP_STROPT(authorized_principals_command); \
M_CP_STROPT(authorized_principals_command_user); \
M_CP_STROPT(hostbased_key_types); \
M_CP_STROPT(pubkey_key_types); \
M_CP_STROPT(ca_sign_algorithms); \
M_CP_STROPT(routing_domain); \
M_CP_STROPT(permit_user_env_whitelist); \
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
M_CP_STRARRAYOPT(deny_users, num_deny_users); \
M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \
M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \
} while (0)
-struct connection_info *get_connection_info(int, int);
+struct connection_info *get_connection_info(struct ssh *, int, int);
void initialize_server_options(ServerOptions *);
void fill_default_server_options(ServerOptions *);
int process_server_config_line(ServerOptions *, char *, const char *, int,
int *, struct connection_info *);
void process_permitopen(struct ssh *ssh, ServerOptions *options);
void load_server_config(const char *, struct sshbuf *);
void parse_server_config(ServerOptions *, const char *, struct sshbuf *,
struct connection_info *);
void parse_server_match_config(ServerOptions *, struct connection_info *);
int parse_server_match_testspec(struct connection_info *, char *);
int server_match_spec_complete(struct connection_info *);
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
void dump_config(ServerOptions *);
char *derelativise_path(const char *);
void servconf_add_hostkey(const char *, const int,
- ServerOptions *, const char *path);
+ ServerOptions *, const char *path, int);
void servconf_add_hostcert(const char *, const int,
ServerOptions *, const char *path);
#endif /* SERVCONF_H */
diff --git a/serverloop.c b/serverloop.c
index 7be83e2d338a..d7b04b37c696 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,921 +1,982 @@
-/* $OpenBSD: serverloop.c,v 1.209 2018/07/27 05:13:02 dtucker Exp $ */
+/* $OpenBSD: serverloop.c,v 1.215 2019/03/27 09:29:14 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Server main loop for handling the interactive session.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 support by Markus Friedl.
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
+#include <limits.h>
#include <signal.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdarg.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "packet.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "canohost.h"
#include "sshpty.h"
#include "channels.h"
#include "compat.h"
#include "ssh2.h"
#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "hostfile.h"
#include "auth.h"
#include "session.h"
#include "dispatch.h"
#include "auth-options.h"
#include "serverloop.h"
#include "ssherr.h"
extern ServerOptions options;
/* XXX */
extern Authctxt *the_authctxt;
extern struct sshauthopt *auth_opts;
extern int use_privsep;
static int no_more_sessions = 0; /* Disallow further sessions. */
/*
* This SIGCHLD kludge is used to detect when the child exits. The server
* will exit after that, as soon as forwarded connections have terminated.
*/
static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */
/* Cleanup on signals (!use_privsep case only) */
static volatile sig_atomic_t received_sigterm = 0;
/* prototypes */
-static void server_init_dispatch(void);
+static void server_init_dispatch(struct ssh *);
/* requested tunnel forwarding interface(s), shared with session.c */
char *tun_fwd_ifnames = NULL;
/* returns 1 if bind to specified port by specified user is permitted */
static int
bind_permitted(int port, uid_t uid)
{
if (use_privsep)
return 1; /* allow system to decide */
if (port < IPPORT_RESERVED && uid != 0)
return 0;
return 1;
}
/*
* we write to this pipe if a SIGCHLD is caught in order to avoid
* the race between select() and child_terminated
*/
static int notify_pipe[2];
static void
notify_setup(void)
{
if (pipe(notify_pipe) < 0) {
error("pipe(notify_pipe) failed %s", strerror(errno));
} else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
(fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
close(notify_pipe[0]);
close(notify_pipe[1]);
} else {
set_nonblock(notify_pipe[0]);
set_nonblock(notify_pipe[1]);
return;
}
notify_pipe[0] = -1; /* read end */
notify_pipe[1] = -1; /* write end */
}
static void
notify_parent(void)
{
if (notify_pipe[1] != -1)
(void)write(notify_pipe[1], "", 1);
}
static void
notify_prepare(fd_set *readset)
{
if (notify_pipe[0] != -1)
FD_SET(notify_pipe[0], readset);
}
static void
notify_done(fd_set *readset)
{
char c;
if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
while (read(notify_pipe[0], &c, 1) != -1)
debug2("%s: reading", __func__);
}
/*ARGSUSED*/
static void
sigchld_handler(int sig)
{
int save_errno = errno;
child_terminated = 1;
notify_parent();
errno = save_errno;
}
/*ARGSUSED*/
static void
sigterm_handler(int sig)
{
received_sigterm = sig;
}
static void
client_alive_check(struct ssh *ssh)
{
- int channel_id;
char remote_id[512];
+ int r, channel_id;
/* timeout, check to see how many we have had */
- if (packet_inc_alive_timeouts() > options.client_alive_count_max) {
+ if (ssh_packet_inc_alive_timeouts(ssh) >
+ options.client_alive_count_max) {
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
logit("Timeout, client not responding from %s", remote_id);
cleanup_exit(255);
}
/*
* send a bogus global/channel request with "wantreply",
* we should get back a failure
*/
if ((channel_id = channel_find_open(ssh)) == -1) {
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("keepalive@openssh.com");
- packet_put_char(1); /* boolean: want reply */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com"))
+ != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0) /* boolean: want reply */
+ fatal("%s: %s", __func__, ssh_err(r));
} else {
channel_request_start(ssh, channel_id,
"keepalive@openssh.com", 1);
}
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
/*
* Sleep in select() until we can do something. This will initialize the
* select masks. Upon return, the masks will indicate which descriptors
* have data or can accept data. Optionally, a maximum time can be specified
* for the duration of the wait (0 = infinite).
*/
static void
wait_until_can_do_something(struct ssh *ssh,
int connection_in, int connection_out,
fd_set **readsetp, fd_set **writesetp, int *maxfdp,
u_int *nallocp, u_int64_t max_time_ms)
{
struct timeval tv, *tvp;
int ret;
time_t minwait_secs = 0;
int client_alive_scheduled = 0;
+ /* time we last heard from the client OR sent a keepalive */
static time_t last_client_time;
/* Allocate and update select() masks for channel descriptors. */
channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
nallocp, &minwait_secs);
/* XXX need proper deadline system for rekey/client alive */
if (minwait_secs != 0)
max_time_ms = MINIMUM(max_time_ms, (u_int)minwait_secs * 1000);
/*
* if using client_alive, set the max timeout accordingly,
* and indicate that this particular timeout was for client
* alive by setting the client_alive_scheduled flag.
*
* this could be randomized somewhat to make traffic
* analysis more difficult, but we're not doing it yet.
*/
if (options.client_alive_interval) {
uint64_t keepalive_ms =
(uint64_t)options.client_alive_interval * 1000;
- client_alive_scheduled = 1;
- if (max_time_ms == 0 || max_time_ms > keepalive_ms)
+ if (max_time_ms == 0 || max_time_ms > keepalive_ms) {
max_time_ms = keepalive_ms;
+ client_alive_scheduled = 1;
+ }
}
#if 0
/* wrong: bad condition XXX */
if (channel_not_very_much_buffered_data())
#endif
FD_SET(connection_in, *readsetp);
notify_prepare(*readsetp);
/*
* If we have buffered packet data going to the client, mark that
* descriptor.
*/
- if (packet_have_data_to_write())
+ if (ssh_packet_have_data_to_write(ssh))
FD_SET(connection_out, *writesetp);
/*
* If child has terminated and there is enough buffer space to read
* from it, then read as much as is available and exit.
*/
- if (child_terminated && packet_not_very_much_data_to_write())
+ if (child_terminated && ssh_packet_not_very_much_data_to_write(ssh))
if (max_time_ms == 0 || client_alive_scheduled)
max_time_ms = 100;
if (max_time_ms == 0)
tvp = NULL;
else {
tv.tv_sec = max_time_ms / 1000;
tv.tv_usec = 1000 * (max_time_ms % 1000);
tvp = &tv;
}
/* Wait for something to happen, or the timeout to expire. */
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
if (ret == -1) {
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
if (errno != EINTR)
error("select: %.100s", strerror(errno));
} else if (client_alive_scheduled) {
time_t now = monotime();
- if (ret == 0) { /* timeout */
+ /*
+ * If the select timed out, or returned for some other reason
+ * but we haven't heard from the client in time, send keepalive.
+ */
+ if (ret == 0 || (last_client_time != 0 && last_client_time +
+ options.client_alive_interval <= now)) {
client_alive_check(ssh);
- } else if (FD_ISSET(connection_in, *readsetp)) {
last_client_time = now;
- } else if (last_client_time != 0 && last_client_time +
- options.client_alive_interval <= now) {
- client_alive_check(ssh);
+ } else if (FD_ISSET(connection_in, *readsetp)) {
last_client_time = now;
}
}
notify_done(*readsetp);
}
/*
* Processes input from the client and the program. Input data is stored
* in buffers and processed later.
*/
static int
process_input(struct ssh *ssh, fd_set *readset, int connection_in)
{
- int len;
+ int r, len;
char buf[16384];
/* Read and buffer any input data from the client. */
if (FD_ISSET(connection_in, readset)) {
len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
verbose("Connection closed by %.100s port %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
return -1;
} else if (len < 0) {
if (errno != EINTR && errno != EAGAIN &&
errno != EWOULDBLOCK) {
verbose("Read error from remote host "
"%.100s port %d: %.100s",
ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh), strerror(errno));
cleanup_exit(255);
}
} else {
/* Buffer any received data. */
- packet_process_incoming(buf, len);
+ if ((r = ssh_packet_process_incoming(ssh, buf, len))
+ != 0)
+ fatal("%s: ssh_packet_process_incoming: %s",
+ __func__, ssh_err(r));
}
}
return 0;
}
/*
* Sends data from internal buffers to client program stdin.
*/
static void
-process_output(fd_set *writeset, int connection_out)
+process_output(struct ssh *ssh, fd_set *writeset, int connection_out)
{
+ int r;
+
/* Send any buffered packet data to the client. */
- if (FD_ISSET(connection_out, writeset))
- packet_write_poll();
+ if (FD_ISSET(connection_out, writeset)) {
+ if ((r = ssh_packet_write_poll(ssh)) != 0)
+ fatal("%s: ssh_packet_write_poll: %s",
+ __func__, ssh_err(r));
+ }
}
static void
process_buffered_input_packets(struct ssh *ssh)
{
ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
}
static void
collect_children(struct ssh *ssh)
{
pid_t pid;
sigset_t oset, nset;
int status;
/* block SIGCHLD while we check for dead children */
sigemptyset(&nset);
sigaddset(&nset, SIGCHLD);
sigprocmask(SIG_BLOCK, &nset, &oset);
if (child_terminated) {
debug("Received SIGCHLD.");
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
if (pid > 0)
session_close_by_pid(ssh, pid, status);
child_terminated = 0;
}
sigprocmask(SIG_SETMASK, &oset, NULL);
}
void
server_loop2(struct ssh *ssh, Authctxt *authctxt)
{
fd_set *readset = NULL, *writeset = NULL;
int max_fd;
u_int nalloc = 0, connection_in, connection_out;
u_int64_t rekey_timeout_ms = 0;
debug("Entering interactive session for SSH2.");
signal(SIGCHLD, sigchld_handler);
child_terminated = 0;
- connection_in = packet_get_connection_in();
- connection_out = packet_get_connection_out();
+ connection_in = ssh_packet_get_connection_in(ssh);
+ connection_out = ssh_packet_get_connection_out(ssh);
if (!use_privsep) {
signal(SIGTERM, sigterm_handler);
signal(SIGINT, sigterm_handler);
signal(SIGQUIT, sigterm_handler);
}
notify_setup();
max_fd = MAXIMUM(connection_in, connection_out);
max_fd = MAXIMUM(max_fd, notify_pipe[0]);
- server_init_dispatch();
+ server_init_dispatch(ssh);
for (;;) {
process_buffered_input_packets(ssh);
if (!ssh_packet_is_rekeying(ssh) &&
- packet_not_very_much_data_to_write())
+ ssh_packet_not_very_much_data_to_write(ssh))
channel_output_poll(ssh);
- if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh))
- rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
- else
+ if (options.rekey_interval > 0 &&
+ !ssh_packet_is_rekeying(ssh)) {
+ rekey_timeout_ms = ssh_packet_get_rekey_timeout(ssh) *
+ 1000;
+ } else {
rekey_timeout_ms = 0;
+ }
wait_until_can_do_something(ssh, connection_in, connection_out,
&readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
if (received_sigterm) {
logit("Exiting on signal %d", (int)received_sigterm);
/* Clean up sessions, utmp, etc. */
cleanup_exit(255);
}
collect_children(ssh);
if (!ssh_packet_is_rekeying(ssh))
channel_after_select(ssh, readset, writeset);
if (process_input(ssh, readset, connection_in) < 0)
break;
- process_output(writeset, connection_out);
+ process_output(ssh, writeset, connection_out);
}
collect_children(ssh);
free(readset);
free(writeset);
/* free all channels, no more reads and writes */
channel_free_all(ssh);
/* free remaining sessions, e.g. remove wtmp entries */
session_destroy_all(ssh, NULL);
}
static int
server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
{
debug("Got %d/%u for keepalive", type, seq);
/*
* reset timeout, since we got a sane answer from the client.
* even if this was generated by something other than
* the bogus CHANNEL_REQUEST we send for keepalives.
*/
- packet_set_alive_timeouts(0);
+ ssh_packet_set_alive_timeouts(ssh, 0);
return 0;
}
static Channel *
server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
{
Channel *c = NULL;
- char *target, *originator;
- u_short target_port, originator_port;
-
- target = packet_get_string(NULL);
- target_port = packet_get_int();
- originator = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
+ char *target = NULL, *originator = NULL;
+ u_int target_port = 0, originator_port = 0;
+ int r;
+
+ if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &target_port)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ if (target_port > 0xFFFF) {
+ error("%s: invalid target port", __func__);
+ *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
+ goto out;
+ }
+ if (originator_port > 0xFFFF) {
+ error("%s: invalid originator port", __func__);
+ *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
+ goto out;
+ }
- debug("%s: originator %s port %d, target %s port %d", __func__,
+ debug("%s: originator %s port %u, target %s port %u", __func__,
originator, originator_port, target, target_port);
/* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
auth_opts->permit_port_forwarding_flag &&
!options.disable_forwarding) {
c = channel_connect_to_port(ssh, target, target_port,
"direct-tcpip", "direct-tcpip", reason, errmsg);
} else {
logit("refused local port forward: "
"originator %s port %d, target %s port %d",
originator, originator_port, target, target_port);
if (reason != NULL)
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
}
+ out:
free(originator);
free(target);
-
return c;
}
static Channel *
server_request_direct_streamlocal(struct ssh *ssh)
{
Channel *c = NULL;
- char *target, *originator;
- u_short originator_port;
+ char *target = NULL, *originator = NULL;
+ u_int originator_port = 0;
struct passwd *pw = the_authctxt->pw;
+ int r;
if (pw == NULL || !the_authctxt->valid)
fatal("%s: no/invalid user", __func__);
- target = packet_get_string(NULL);
- originator = packet_get_string(NULL);
- originator_port = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ if (originator_port > 0xFFFF) {
+ error("%s: invalid originator port", __func__);
+ goto out;
+ }
debug("%s: originator %s port %d, target %s", __func__,
originator, originator_port, target);
/* XXX fine grained permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
auth_opts->permit_port_forwarding_flag &&
!options.disable_forwarding && (pw->pw_uid == 0 || use_privsep)) {
c = channel_connect_to_path(ssh, target,
"direct-streamlocal@openssh.com", "direct-streamlocal");
} else {
logit("refused streamlocal port forward: "
"originator %s port %d, target %s",
originator, originator_port, target);
}
+out:
free(originator);
free(target);
-
return c;
}
static Channel *
server_request_tun(struct ssh *ssh)
{
Channel *c = NULL;
- int mode, tun, sock;
+ u_int mode, tun;
+ int r, sock;
char *tmp, *ifname = NULL;
- mode = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &mode)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse mode", __func__);
switch (mode) {
case SSH_TUNMODE_POINTOPOINT:
case SSH_TUNMODE_ETHERNET:
break;
default:
- packet_send_debug("Unsupported tunnel device mode.");
+ ssh_packet_send_debug(ssh, "Unsupported tunnel device mode.");
return NULL;
}
if ((options.permit_tun & mode) == 0) {
- packet_send_debug("Server has rejected tunnel device "
+ ssh_packet_send_debug(ssh, "Server has rejected tunnel device "
"forwarding");
return NULL;
}
- tun = packet_get_int();
+ if ((r = sshpkt_get_u32(ssh, &tun)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse device", __func__);
+ if (tun > INT_MAX) {
+ debug("%s: invalid tun", __func__);
+ goto done;
+ }
if (auth_opts->force_tun_device != -1) {
- if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun)
+ if (tun != SSH_TUNID_ANY &&
+ auth_opts->force_tun_device != (int)tun)
goto done;
tun = auth_opts->force_tun_device;
}
sock = tun_open(tun, mode, &ifname);
if (sock < 0)
goto done;
debug("Tunnel forwarding using interface %s", ifname);
c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1;
#if defined(SSH_TUN_FILTER)
if (mode == SSH_TUNMODE_POINTOPOINT)
channel_register_filter(ssh, c->self, sys_tun_infilter,
sys_tun_outfilter, NULL, NULL);
#endif
/*
* Update the list of names exposed to the session
* XXX remove these if the tunnels are closed (won't matter
* much if they are already in the environment though)
*/
tmp = tun_fwd_ifnames;
xasprintf(&tun_fwd_ifnames, "%s%s%s",
tun_fwd_ifnames == NULL ? "" : tun_fwd_ifnames,
tun_fwd_ifnames == NULL ? "" : ",",
ifname);
free(tmp);
free(ifname);
done:
if (c == NULL)
- packet_send_debug("Failed to open the tunnel device.");
+ ssh_packet_send_debug(ssh, "Failed to open the tunnel device.");
return c;
}
static Channel *
server_request_session(struct ssh *ssh)
{
Channel *c;
+ int r;
debug("input_session_request");
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (no_more_sessions) {
- packet_disconnect("Possible attack: attempt to open a session "
- "after additional sessions disabled");
+ ssh_packet_disconnect(ssh, "Possible attack: attempt to open a "
+ "session after additional sessions disabled");
}
/*
* A server session has no fd to read or write until a
* CHANNEL_REQUEST for a shell is made, so we set the type to
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered.
*/
c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
-1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
0, "server-session", 1);
if (session_open(the_authctxt, c->self) != 1) {
debug("session open failed, free channel %d", c->self);
channel_free(ssh, c);
return NULL;
}
channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
return c;
}
static int
server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c = NULL;
- char *ctype;
+ char *ctype = NULL;
const char *errmsg = NULL;
- int rchan, reason = SSH2_OPEN_CONNECT_FAILED;
- u_int rmaxpack, rwindow, len;
-
- ctype = packet_get_string(&len);
- rchan = packet_get_int();
- rwindow = packet_get_int();
- rmaxpack = packet_get_int();
-
- debug("%s: ctype %s rchan %d win %d max %d", __func__,
+ int r, reason = SSH2_OPEN_CONNECT_FAILED;
+ u_int rchan = 0, rmaxpack = 0, rwindow = 0;
+
+ if ((r = sshpkt_get_cstring(ssh, &ctype, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rchan)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+ debug("%s: ctype %s rchan %u win %u max %u", __func__,
ctype, rchan, rwindow, rmaxpack);
- if (strcmp(ctype, "session") == 0) {
+ if (rchan > INT_MAX) {
+ error("%s: invalid remote channel ID", __func__);
+ } else if (strcmp(ctype, "session") == 0) {
c = server_request_session(ssh);
} else if (strcmp(ctype, "direct-tcpip") == 0) {
c = server_request_direct_tcpip(ssh, &reason, &errmsg);
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
c = server_request_direct_streamlocal(ssh);
} else if (strcmp(ctype, "tun@openssh.com") == 0) {
c = server_request_tun(ssh);
}
if (c != NULL) {
debug("%s: confirm %s", __func__, ctype);
- c->remote_id = rchan;
+ c->remote_id = (int)rchan;
c->have_remote_id = 1;
c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack;
if (c->type != SSH_CHANNEL_CONNECTING) {
- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
- packet_put_int(c->remote_id);
- packet_put_int(c->self);
- packet_put_int(c->local_window);
- packet_put_int(c->local_maxpacket);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->self)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: send open confirm", __func__);
+ }
}
} else {
debug("%s: failure %s", __func__, ctype);
- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
- packet_put_int(rchan);
- packet_put_int(reason);
- packet_put_cstring(errmsg ? errmsg : "open failed");
- packet_put_cstring("");
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, rchan)) != 0 ||
+ (r = sshpkt_put_u32(ssh, reason)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, errmsg ? errmsg : "open failed")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: send open failure", __func__);
+ }
}
free(ctype);
return 0;
}
static int
server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
{
struct sshbuf *resp = NULL;
struct sshbuf *sigbuf = NULL;
struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
int r, ndx, kexsigtype, use_kexsigtype, success = 0;
const u_char *blob;
u_char *sig = 0;
size_t blen, slen;
if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
kexsigtype = sshkey_type_plain(
sshkey_type_from_name(ssh->kex->hostkey_alg));
while (ssh_packet_remaining(ssh) > 0) {
sshkey_free(key);
key = NULL;
if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
(r = sshkey_from_blob(blob, blen, &key)) != 0) {
error("%s: couldn't parse key: %s",
__func__, ssh_err(r));
goto out;
}
/*
* Better check that this is actually one of our hostkeys
* before attempting to sign anything with it.
*/
if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
error("%s: unknown host %s key",
__func__, sshkey_type(key));
goto out;
}
/*
* XXX refactor: make kex->sign just use an index rather
* than passing in public and private keys
*/
if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
(key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
error("%s: can't retrieve hostkey %d", __func__, ndx);
goto out;
}
sshbuf_reset(sigbuf);
free(sig);
sig = NULL;
/*
* For RSA keys, prefer to use the signature type negotiated
* during KEX to the default (SHA1).
*/
use_kexsigtype = kexsigtype == KEY_RSA &&
sshkey_type_plain(key->type) == KEY_RSA;
if ((r = sshbuf_put_cstring(sigbuf,
"hostkeys-prove-00@openssh.com")) != 0 ||
(r = sshbuf_put_string(sigbuf,
ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
(r = sshkey_puts(key, sigbuf)) != 0 ||
- (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
+ (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen,
sshbuf_ptr(sigbuf), sshbuf_len(sigbuf),
- use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0)) != 0 ||
+ use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 ||
(r = sshbuf_put_string(resp, sig, slen)) != 0) {
error("%s: couldn't prepare signature: %s",
__func__, ssh_err(r));
goto out;
}
}
/* Success */
*respp = resp;
resp = NULL; /* don't free it */
success = 1;
out:
free(sig);
sshbuf_free(resp);
sshbuf_free(sigbuf);
sshkey_free(key);
return success;
}
static int
server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
{
- char *rtype;
- int want_reply;
+ char *rtype = NULL;
+ u_char want_reply = 0;
int r, success = 0, allocated_listen_port = 0;
+ u_int port = 0;
struct sshbuf *resp = NULL;
struct passwd *pw = the_authctxt->pw;
+ struct Forward fwd;
+ memset(&fwd, 0, sizeof(fwd));
if (pw == NULL || !the_authctxt->valid)
fatal("%s: no/invalid user", __func__);
- rtype = packet_get_string(NULL);
- want_reply = packet_get_char();
+ if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
debug("%s: rtype %s want_reply %d", __func__, rtype, want_reply);
/* -R style forwarding */
if (strcmp(rtype, "tcpip-forward") == 0) {
- struct Forward fwd;
-
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_host = packet_get_string(NULL);
- fwd.listen_port = (u_short)packet_get_int();
- debug("%s: tcpip-forward listen %s port %d", __func__,
- fwd.listen_host, fwd.listen_port);
-
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &port)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__);
+ debug("%s: tcpip-forward listen %s port %u", __func__,
+ fwd.listen_host, port);
+ if (port <= INT_MAX)
+ fwd.listen_port = (int)port;
/* check permissions */
- if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
+ if (port > INT_MAX ||
+ (options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
!auth_opts->permit_port_forwarding_flag ||
options.disable_forwarding ||
(!want_reply && fwd.listen_port == 0) ||
(fwd.listen_port != 0 &&
!bind_permitted(fwd.listen_port, pw->pw_uid))) {
success = 0;
- packet_send_debug("Server has disabled port forwarding.");
+ ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
} else {
/* Start listening on the port */
success = channel_setup_remote_fwd_listener(ssh, &fwd,
&allocated_listen_port, &options.fwd_opts);
}
- free(fwd.listen_host);
if ((resp = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
if (allocated_listen_port != 0 &&
(r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
- struct Forward fwd;
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &port)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__);
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_host = packet_get_string(NULL);
- fwd.listen_port = (u_short)packet_get_int();
debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
- fwd.listen_host, fwd.listen_port);
-
- success = channel_cancel_rport_listener(ssh, &fwd);
- free(fwd.listen_host);
+ fwd.listen_host, port);
+ if (port <= INT_MAX) {
+ fwd.listen_port = (int)port;
+ success = channel_cancel_rport_listener(ssh, &fwd);
+ }
} else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
- struct Forward fwd;
-
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_path = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward@openssh.com", __func__);
debug("%s: streamlocal-forward listen path %s", __func__,
fwd.listen_path);
/* check permissions */
if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
|| !auth_opts->permit_port_forwarding_flag ||
options.disable_forwarding ||
(pw->pw_uid != 0 && !use_privsep)) {
success = 0;
- packet_send_debug("Server has disabled "
+ ssh_packet_send_debug(ssh, "Server has disabled "
"streamlocal forwarding.");
} else {
/* Start listening on the socket */
success = channel_setup_remote_fwd_listener(ssh,
&fwd, NULL, &options.fwd_opts);
}
- free(fwd.listen_path);
} else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
- struct Forward fwd;
-
- memset(&fwd, 0, sizeof(fwd));
- fwd.listen_path = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward@openssh.com", __func__);
debug("%s: cancel-streamlocal-forward path %s", __func__,
fwd.listen_path);
success = channel_cancel_rport_listener(ssh, &fwd);
- free(fwd.listen_path);
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
no_more_sessions = 1;
success = 1;
} else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) {
success = server_input_hostkeys_prove(ssh, &resp);
}
+ /* XXX sshpkt_get_end() */
if (want_reply) {
- packet_start(success ?
- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
- if (success && resp != NULL)
- ssh_packet_put_raw(ssh, sshbuf_ptr(resp),
- sshbuf_len(resp));
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, success ?
+ SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 ||
+ (success && resp != NULL && (r = sshpkt_putb(ssh, resp)) != 0) ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
}
+ free(fwd.listen_host);
+ free(fwd.listen_path);
free(rtype);
sshbuf_free(resp);
return 0;
}
static int
server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
{
Channel *c;
- int id, reply, success = 0;
- char *rtype;
-
- id = packet_get_int();
- rtype = packet_get_string(NULL);
- reply = packet_get_char();
-
- debug("server_input_channel_req: channel %d request %s reply %d",
- id, rtype, reply);
-
- if ((c = channel_lookup(ssh, id)) == NULL)
- packet_disconnect("server_input_channel_req: "
- "unknown channel %d", id);
+ int r, success = 0;
+ char *rtype = NULL;
+ u_char want_reply = 0;
+ u_int id = 0;
+
+ if ((r = sshpkt_get_u32(ssh, &id)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
+ (r = sshpkt_get_u8(ssh, &want_reply)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+
+ debug("server_input_channel_req: channel %u request %s reply %d",
+ id, rtype, want_reply);
+
+ if (id >= INT_MAX || (c = channel_lookup(ssh, (int)id)) == NULL) {
+ ssh_packet_disconnect(ssh, "%s: unknown channel %d",
+ __func__, id);
+ }
if (!strcmp(rtype, "eow@openssh.com")) {
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
chan_rcvd_eow(ssh, c);
} else if ((c->type == SSH_CHANNEL_LARVAL ||
c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
success = session_input_channel_req(ssh, c, rtype);
- if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
+ if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) {
if (!c->have_remote_id)
fatal("%s: channel %d: no remote_id",
__func__, c->self);
- packet_start(success ?
- SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
- packet_put_int(c->remote_id);
- packet_send();
+ if ((r = sshpkt_start(ssh, success ?
+ SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
+ (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send reply", __func__);
}
free(rtype);
return 0;
}
static void
-server_init_dispatch(void)
+server_init_dispatch(struct ssh *ssh)
{
debug("server_init_dispatch");
- dispatch_init(&dispatch_protocol_error);
- dispatch_set(SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
- dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data);
- dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
- dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
- dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
- dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
- dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
- dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
+ ssh_dispatch_init(ssh, &dispatch_protocol_error);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &server_input_channel_open);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &server_input_channel_req);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
+ ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
/* client_alive */
- dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
- dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
- dispatch_set(SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
- dispatch_set(SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &server_input_keep_alive);
+ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &server_input_keep_alive);
/* rekeying */
- dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
}
diff --git a/session.c b/session.c
index 2d0958d112e7..ac06b08e957c 100644
--- a/session.c
+++ b/session.c
@@ -1,2714 +1,2719 @@
-/* $OpenBSD: session.c,v 1.307 2018/10/04 00:10:11 djm Exp $ */
+/* $OpenBSD: session.c,v 1.315 2019/02/22 03:37:11 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 support by Markus Friedl.
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "sshpty.h"
#include "packet.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "match.h"
#include "uidswap.h"
#include "compat.h"
#include "channels.h"
#include "sshkey.h"
#include "cipher.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "hostfile.h"
#include "auth.h"
#include "auth-options.h"
#include "authfd.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "servconf.h"
#include "sshlogin.h"
#include "serverloop.h"
#include "canohost.h"
#include "session.h"
#include "kex.h"
#include "monitor_wrap.h"
#include "sftp.h"
#include "atomicio.h"
#if defined(KRB5) && defined(USE_AFS)
#include <kafs.h>
#endif
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#endif
#define IS_INTERNAL_SFTP(c) \
(!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
(c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
c[sizeof(INTERNAL_SFTP_NAME) - 1] == ' ' || \
c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\t'))
/* func */
Session *session_new(void);
void session_set_fds(struct ssh *, Session *, int, int, int, int, int);
void session_pty_cleanup(Session *);
void session_proctitle(Session *);
int session_setup_x11fwd(struct ssh *, Session *);
int do_exec_pty(struct ssh *, Session *, const char *);
int do_exec_no_pty(struct ssh *, Session *, const char *);
int do_exec(struct ssh *, Session *, const char *);
void do_login(struct ssh *, Session *, const char *);
void do_child(struct ssh *, Session *, const char *);
-#ifdef LOGIN_NEEDS_UTMPX
-static void do_pre_login(Session *s);
-#endif
void do_motd(void);
int check_quietlogin(Session *, const char *);
static void do_authenticated2(struct ssh *, Authctxt *);
static int session_pty_req(struct ssh *, Session *);
/* import */
extern ServerOptions options;
extern char *__progname;
extern int debug_flag;
extern u_int utmp_len;
extern int startup_pipe;
extern void destroy_sensitive_data(void);
extern struct sshbuf *loginmsg;
extern struct sshauthopt *auth_opts;
-char *tun_fwd_ifnames; /* serverloop.c */
+extern char *tun_fwd_ifnames; /* serverloop.c */
/* original command from peer. */
const char *original_command = NULL;
/* data */
static int sessions_first_unused = -1;
static int sessions_nalloc = 0;
static Session *sessions = NULL;
#define SUBSYSTEM_NONE 0
#define SUBSYSTEM_EXT 1
#define SUBSYSTEM_INT_SFTP 2
#define SUBSYSTEM_INT_SFTP_ERROR 3
#ifdef HAVE_LOGIN_CAP
login_cap_t *lc;
#endif
static int is_child = 0;
static int in_chroot = 0;
/* File containing userauth info, if ExposeAuthInfo set */
static char *auth_info_file = NULL;
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
static char *auth_sock_dir = NULL;
/* removes the agent forwarding socket */
static void
auth_sock_cleanup_proc(struct passwd *pw)
{
if (auth_sock_name != NULL) {
temporarily_use_uid(pw);
unlink(auth_sock_name);
rmdir(auth_sock_dir);
auth_sock_name = NULL;
restore_uid();
}
}
static int
auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw)
{
Channel *nc;
int sock = -1;
if (auth_sock_name != NULL) {
error("authentication forwarding requested twice.");
return 0;
}
/* Temporarily drop privileged uid for mkdir/bind. */
temporarily_use_uid(pw);
/* Allocate a buffer for the socket name, and format the name. */
auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
/* Create private directory for socket */
if (mkdtemp(auth_sock_dir) == NULL) {
- packet_send_debug("Agent forwarding disabled: "
+ ssh_packet_send_debug(ssh, "Agent forwarding disabled: "
"mkdtemp() failed: %.100s", strerror(errno));
restore_uid();
free(auth_sock_dir);
auth_sock_dir = NULL;
goto authsock_err;
}
xasprintf(&auth_sock_name, "%s/agent.%ld",
auth_sock_dir, (long) getpid());
/* Start a Unix listener on auth_sock_name. */
sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
/* Restore the privileged uid. */
restore_uid();
/* Check for socket/bind/listen failure. */
if (sock < 0)
goto authsock_err;
/* Allocate a channel for the authentication agent socket. */
nc = channel_new(ssh, "auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, "auth socket", 1);
nc->path = xstrdup(auth_sock_name);
return 1;
authsock_err:
free(auth_sock_name);
if (auth_sock_dir != NULL) {
+ temporarily_use_uid(pw);
rmdir(auth_sock_dir);
+ restore_uid();
free(auth_sock_dir);
}
if (sock != -1)
close(sock);
auth_sock_name = NULL;
auth_sock_dir = NULL;
return 0;
}
static void
display_loginmsg(void)
{
int r;
if (sshbuf_len(loginmsg) == 0)
return;
if ((r = sshbuf_put_u8(loginmsg, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
printf("%s", (char *)sshbuf_ptr(loginmsg));
sshbuf_reset(loginmsg);
}
static void
prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
{
int fd = -1, success = 0;
if (!options.expose_userauth_info || info == NULL)
return;
temporarily_use_uid(pw);
auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX");
if ((fd = mkstemp(auth_info_file)) == -1) {
error("%s: mkstemp: %s", __func__, strerror(errno));
goto out;
}
if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info),
sshbuf_len(info)) != sshbuf_len(info)) {
error("%s: write: %s", __func__, strerror(errno));
goto out;
}
if (close(fd) != 0) {
error("%s: close: %s", __func__, strerror(errno));
goto out;
}
success = 1;
out:
if (!success) {
if (fd != -1)
close(fd);
free(auth_info_file);
auth_info_file = NULL;
}
restore_uid();
}
static void
set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
{
char *tmp, *cp, *host;
int port;
size_t i;
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) {
channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL);
for (i = 0; i < auth_opts->npermitopen; i++) {
tmp = cp = xstrdup(auth_opts->permitopen[i]);
/* This shouldn't fail as it has already been checked */
if ((host = hpdelim(&cp)) == NULL)
fatal("%s: internal error: hpdelim", __func__);
host = cleanhostname(host);
if (cp == NULL || (port = permitopen_port(cp)) < 0)
fatal("%s: internal error: permitopen port",
__func__);
channel_add_permission(ssh,
FORWARD_USER, FORWARD_LOCAL, host, port);
free(tmp);
}
}
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) != 0) {
channel_clear_permission(ssh, FORWARD_USER, FORWARD_REMOTE);
for (i = 0; i < auth_opts->npermitlisten; i++) {
tmp = cp = xstrdup(auth_opts->permitlisten[i]);
/* This shouldn't fail as it has already been checked */
if ((host = hpdelim(&cp)) == NULL)
fatal("%s: internal error: hpdelim", __func__);
host = cleanhostname(host);
if (cp == NULL || (port = permitopen_port(cp)) < 0)
fatal("%s: internal error: permitlisten port",
__func__);
channel_add_permission(ssh,
FORWARD_USER, FORWARD_REMOTE, host, port);
free(tmp);
}
}
}
void
do_authenticated(struct ssh *ssh, Authctxt *authctxt)
{
setproctitle("%s", authctxt->pw->pw_name);
auth_log_authopts("active", auth_opts, 0);
/* setup the channel layer */
/* XXX - streamlocal? */
set_fwdpermit_from_authopts(ssh, auth_opts);
if (!auth_opts->permit_port_forwarding_flag ||
options.disable_forwarding) {
channel_disable_admin(ssh, FORWARD_LOCAL);
channel_disable_admin(ssh, FORWARD_REMOTE);
} else {
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
channel_disable_admin(ssh, FORWARD_LOCAL);
else
channel_permit_all(ssh, FORWARD_LOCAL);
if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0)
channel_disable_admin(ssh, FORWARD_REMOTE);
else
channel_permit_all(ssh, FORWARD_REMOTE);
}
- auth_debug_send();
+ auth_debug_send(ssh);
prepare_auth_info_file(authctxt->pw, authctxt->session_info);
do_authenticated2(ssh, authctxt);
do_cleanup(ssh, authctxt);
}
/* Check untrusted xauth strings for metacharacters */
static int
xauth_valid_string(const char *s)
{
size_t i;
for (i = 0; s[i] != '\0'; i++) {
if (!isalnum((u_char)s[i]) &&
s[i] != '.' && s[i] != ':' && s[i] != '/' &&
s[i] != '-' && s[i] != '_')
return 0;
}
return 1;
}
#define USE_PIPES 1
/*
* This is called to fork and execute a command when we have no tty. This
* will call do_child from the child, and server_loop from the parent after
* setting up file descriptors and such.
*/
int
do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
{
pid_t pid;
#ifdef USE_PIPES
int pin[2], pout[2], perr[2];
if (s == NULL)
fatal("do_exec_no_pty: no session");
/* Allocate pipes for communicating with the program. */
if (pipe(pin) < 0) {
error("%s: pipe in: %.100s", __func__, strerror(errno));
return -1;
}
if (pipe(pout) < 0) {
error("%s: pipe out: %.100s", __func__, strerror(errno));
close(pin[0]);
close(pin[1]);
return -1;
}
if (pipe(perr) < 0) {
error("%s: pipe err: %.100s", __func__,
strerror(errno));
close(pin[0]);
close(pin[1]);
close(pout[0]);
close(pout[1]);
return -1;
}
#else
int inout[2], err[2];
if (s == NULL)
fatal("do_exec_no_pty: no session");
/* Uses socket pairs to communicate with the program. */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
error("%s: socketpair #1: %.100s", __func__, strerror(errno));
return -1;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
error("%s: socketpair #2: %.100s", __func__,
strerror(errno));
close(inout[0]);
close(inout[1]);
return -1;
}
#endif
session_proctitle(s);
/* Fork the child. */
switch ((pid = fork())) {
case -1:
error("%s: fork: %.100s", __func__, strerror(errno));
#ifdef USE_PIPES
close(pin[0]);
close(pin[1]);
close(pout[0]);
close(pout[1]);
close(perr[0]);
close(perr[1]);
#else
close(inout[0]);
close(inout[1]);
close(err[0]);
close(err[1]);
#endif
return -1;
case 0:
is_child = 1;
/*
* Create a new session and process group since the 4.4BSD
* setlogin() affects the entire process group.
*/
if (setsid() < 0)
error("setsid failed: %.100s", strerror(errno));
#ifdef USE_PIPES
/*
* Redirect stdin. We close the parent side of the socket
* pair, and make the child side the standard input.
*/
close(pin[1]);
if (dup2(pin[0], 0) < 0)
perror("dup2 stdin");
close(pin[0]);
/* Redirect stdout. */
close(pout[0]);
if (dup2(pout[1], 1) < 0)
perror("dup2 stdout");
close(pout[1]);
/* Redirect stderr. */
close(perr[0]);
if (dup2(perr[1], 2) < 0)
perror("dup2 stderr");
close(perr[1]);
#else
/*
* Redirect stdin, stdout, and stderr. Stdin and stdout will
* use the same socket, as some programs (particularly rdist)
* seem to depend on it.
*/
close(inout[1]);
close(err[1]);
if (dup2(inout[0], 0) < 0) /* stdin */
perror("dup2 stdin");
if (dup2(inout[0], 1) < 0) /* stdout (same as stdin) */
perror("dup2 stdout");
close(inout[0]);
if (dup2(err[0], 2) < 0) /* stderr */
perror("dup2 stderr");
close(err[0]);
#endif
/* Do processing for the child (exec command etc). */
do_child(ssh, s, command);
/* NOTREACHED */
default:
break;
}
#ifdef HAVE_CYGWIN
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
s->pid = pid;
/* Set interactive/non-interactive mode. */
- packet_set_interactive(s->display != NULL,
+ ssh_packet_set_interactive(ssh, s->display != NULL,
options.ip_qos_interactive, options.ip_qos_bulk);
/*
* Clear loginmsg, since it's the child's responsibility to display
* it to the user, otherwise multiple sessions may accumulate
* multiple copies of the login messages.
*/
sshbuf_reset(loginmsg);
#ifdef USE_PIPES
/* We are the parent. Close the child sides of the pipes. */
close(pin[0]);
close(pout[1]);
close(perr[1]);
session_set_fds(ssh, s, pin[1], pout[0], perr[0],
s->is_subsystem, 0);
#else
/* We are the parent. Close the child sides of the socket pairs. */
close(inout[0]);
close(err[0]);
/*
* Enter the interactive session. Note: server_loop must be able to
* handle the case that fdin and fdout are the same.
*/
- session_set_fds(s, inout[1], inout[1], err[1],
+ session_set_fds(ssh, s, inout[1], inout[1], err[1],
s->is_subsystem, 0);
#endif
return 0;
}
/*
* This is called to fork and execute a command when we have a tty. This
* will call do_child from the child, and server_loop from the parent after
* setting up file descriptors, controlling tty, updating wtmp, utmp,
* lastlog, and other such operations.
*/
int
do_exec_pty(struct ssh *ssh, Session *s, const char *command)
{
int fdout, ptyfd, ttyfd, ptymaster;
pid_t pid;
if (s == NULL)
fatal("do_exec_pty: no session");
ptyfd = s->ptyfd;
ttyfd = s->ttyfd;
/*
* Create another descriptor of the pty master side for use as the
* standard input. We could use the original descriptor, but this
* simplifies code in server_loop. The descriptor is bidirectional.
* Do this before forking (and cleanup in the child) so as to
* detect and gracefully fail out-of-fd conditions.
*/
if ((fdout = dup(ptyfd)) < 0) {
error("%s: dup #1: %s", __func__, strerror(errno));
close(ttyfd);
close(ptyfd);
return -1;
}
/* we keep a reference to the pty master */
if ((ptymaster = dup(ptyfd)) < 0) {
error("%s: dup #2: %s", __func__, strerror(errno));
close(ttyfd);
close(ptyfd);
close(fdout);
return -1;
}
/* Fork the child. */
switch ((pid = fork())) {
case -1:
error("%s: fork: %.100s", __func__, strerror(errno));
close(fdout);
close(ptymaster);
close(ttyfd);
close(ptyfd);
return -1;
case 0:
is_child = 1;
close(fdout);
close(ptymaster);
/* Close the master side of the pseudo tty. */
close(ptyfd);
/* Make the pseudo tty our controlling tty. */
pty_make_controlling_tty(&ttyfd, s->tty);
/* Redirect stdin/stdout/stderr from the pseudo tty. */
if (dup2(ttyfd, 0) < 0)
error("dup2 stdin: %s", strerror(errno));
if (dup2(ttyfd, 1) < 0)
error("dup2 stdout: %s", strerror(errno));
if (dup2(ttyfd, 2) < 0)
error("dup2 stderr: %s", strerror(errno));
/* Close the extra descriptor for the pseudo tty. */
close(ttyfd);
/* record login, etc. similar to login(1) */
#ifndef HAVE_OSF_SIA
do_login(ssh, s, command);
#endif
/*
* Do common processing for the child, such as execing
* the command.
*/
do_child(ssh, s, command);
/* NOTREACHED */
default:
break;
}
#ifdef HAVE_CYGWIN
cygwin_set_impersonation_token(INVALID_HANDLE_VALUE);
#endif
s->pid = pid;
/* Parent. Close the slave side of the pseudo tty. */
close(ttyfd);
/* Enter interactive session. */
s->ptymaster = ptymaster;
- packet_set_interactive(1,
+ ssh_packet_set_interactive(ssh, 1,
options.ip_qos_interactive, options.ip_qos_bulk);
session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1);
return 0;
}
-#ifdef LOGIN_NEEDS_UTMPX
-static void
-do_pre_login(Session *s)
-{
- struct ssh *ssh = active_state; /* XXX */
- socklen_t fromlen;
- struct sockaddr_storage from;
- pid_t pid = getpid();
-
- /*
- * Get IP address of client. If the connection is not a socket, let
- * the address be 0.0.0.0.
- */
- memset(&from, 0, sizeof(from));
- fromlen = sizeof(from);
- if (packet_connection_is_on_socket()) {
- if (getpeername(packet_get_connection_in(),
- (struct sockaddr *)&from, &fromlen) < 0) {
- debug("getpeername: %.100s", strerror(errno));
- cleanup_exit(255);
- }
- }
-
- record_utmp_only(pid, s->tty, s->pw->pw_name,
- session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns),
- (struct sockaddr *)&from, fromlen);
-}
-#endif
-
/*
* This is called to fork and execute a command. If another command is
* to be forced, execute that instead.
*/
int
do_exec(struct ssh *ssh, Session *s, const char *command)
{
int ret;
const char *forced = NULL, *tty = NULL;
char session_type[1024];
if (options.adm_forced_command) {
original_command = command;
command = options.adm_forced_command;
forced = "(config)";
} else if (auth_opts->force_command != NULL) {
original_command = command;
command = auth_opts->force_command;
forced = "(key-option)";
}
s->forced = 0;
if (forced != NULL) {
s->forced = 1;
if (IS_INTERNAL_SFTP(command)) {
s->is_subsystem = s->is_subsystem ?
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
} else if (s->is_subsystem)
s->is_subsystem = SUBSYSTEM_EXT;
snprintf(session_type, sizeof(session_type),
"forced-command %s '%.900s'", forced, command);
} else if (s->is_subsystem) {
snprintf(session_type, sizeof(session_type),
"subsystem '%.900s'", s->subsys);
} else if (command == NULL) {
snprintf(session_type, sizeof(session_type), "shell");
} else {
/* NB. we don't log unforced commands to preserve privacy */
snprintf(session_type, sizeof(session_type), "command");
}
if (s->ttyfd != -1) {
tty = s->tty;
if (strncmp(tty, "/dev/", 5) == 0)
tty += 5;
}
verbose("Starting session: %s%s%s for %s from %.200s port %d id %d",
session_type,
tty == NULL ? "" : " on ",
tty == NULL ? "" : tty,
s->pw->pw_name,
ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh),
s->self);
#ifdef SSH_AUDIT_EVENTS
if (command != NULL)
PRIVSEP(audit_run_command(command));
else if (s->ttyfd == -1) {
char *shell = s->pw->pw_shell;
if (shell[0] == '\0') /* empty shell means /bin/sh */
shell =_PATH_BSHELL;
PRIVSEP(audit_run_command(shell));
}
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(ssh, s, command);
else
ret = do_exec_no_pty(ssh, s, command);
original_command = NULL;
/*
* Clear loginmsg: it's the child's responsibility to display
* it to the user, otherwise multiple sessions may accumulate
* multiple copies of the login messages.
*/
sshbuf_reset(loginmsg);
return ret;
}
/* administrative, login(1)-like work */
void
do_login(struct ssh *ssh, Session *s, const char *command)
{
socklen_t fromlen;
struct sockaddr_storage from;
struct passwd * pw = s->pw;
pid_t pid = getpid();
/*
* Get IP address of client. If the connection is not a socket, let
* the address be 0.0.0.0.
*/
memset(&from, 0, sizeof(from));
fromlen = sizeof(from);
- if (packet_connection_is_on_socket()) {
- if (getpeername(packet_get_connection_in(),
+ if (ssh_packet_connection_is_on_socket(ssh)) {
+ if (getpeername(ssh_packet_get_connection_in(ssh),
(struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername: %.100s", strerror(errno));
cleanup_exit(255);
}
}
/* Record that there was a login on that tty from the remote host. */
if (!use_privsep)
record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
session_get_remote_name_or_ip(ssh, utmp_len,
options.use_dns),
(struct sockaddr *)&from, fromlen);
#ifdef USE_PAM
/*
* If password change is needed, do it now.
* This needs to occur before the ~/.hushlogin check.
*/
if (options.use_pam && !use_privsep && s->authctxt->force_pwchange) {
display_loginmsg();
do_pam_chauthtok();
s->authctxt->force_pwchange = 0;
/* XXX - signal [net] parent to enable forwardings */
}
#endif
if (check_quietlogin(s, command))
return;
display_loginmsg();
do_motd();
}
/*
* Display the message of the day.
*/
void
do_motd(void)
{
FILE *f;
char buf[256];
if (options.print_motd) {
#ifdef HAVE_LOGIN_CAP
f = fopen(login_getcapstr(lc, "welcome", "/etc/motd",
"/etc/motd"), "r");
#else
f = fopen("/etc/motd", "r");
#endif
if (f) {
while (fgets(buf, sizeof(buf), f))
fputs(buf, stdout);
fclose(f);
}
}
}
/*
* Check for quiet login, either .hushlogin or command given.
*/
int
check_quietlogin(Session *s, const char *command)
{
char buf[256];
struct passwd *pw = s->pw;
struct stat st;
/* Return 1 if .hushlogin exists or a command given. */
if (command != NULL)
return 1;
snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir);
#ifdef HAVE_LOGIN_CAP
if (login_getcapbool(lc, "hushlogin", 0) || stat(buf, &st) >= 0)
return 1;
#else
if (stat(buf, &st) >= 0)
return 1;
#endif
return 0;
}
/*
* Reads environment variables from the given file and adds/overrides them
* into the environment. If the file does not exist, this does nothing.
* Otherwise, it must consist of empty lines, comments (line starts with '#')
* and assignments of the form name=value. No other forms are allowed.
* If whitelist is not NULL, then it is interpreted as a pattern list and
* only variable names that match it will be accepted.
*/
static void
read_environment_file(char ***env, u_int *envsize,
const char *filename, const char *whitelist)
{
FILE *f;
char *line = NULL, *cp, *value;
size_t linesize = 0;
u_int lineno = 0;
f = fopen(filename, "r");
if (!f)
return;
while (getline(&line, &linesize, f) != -1) {
if (++lineno > 1000)
fatal("Too many lines in environment file %s", filename);
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '#' || *cp == '\n')
continue;
cp[strcspn(cp, "\n")] = '\0';
value = strchr(cp, '=');
if (value == NULL) {
fprintf(stderr, "Bad line %u in %.100s\n", lineno,
filename);
continue;
}
/*
* Replace the equals sign by nul, and advance value to
* the value string.
*/
*value = '\0';
value++;
if (whitelist != NULL &&
match_pattern_list(cp, whitelist, 0) != 1)
continue;
child_set_env(env, envsize, cp, value);
}
free(line);
fclose(f);
}
#ifdef HAVE_ETC_DEFAULT_LOGIN
/*
* Return named variable from specified environment, or NULL if not present.
*/
static char *
child_get_env(char **env, const char *name)
{
int i;
size_t len;
len = strlen(name);
for (i=0; env[i] != NULL; i++)
if (strncmp(name, env[i], len) == 0 && env[i][len] == '=')
return(env[i] + len + 1);
return NULL;
}
/*
* Read /etc/default/login.
* We pick up the PATH (or SUPATH for root) and UMASK.
*/
static void
read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
{
char **tmpenv = NULL, *var;
u_int i, tmpenvsize = 0;
u_long mask;
/*
* We don't want to copy the whole file to the child's environment,
* so we use a temporary environment and copy the variables we're
* interested in.
*/
read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login",
options.permit_user_env_whitelist);
if (tmpenv == NULL)
return;
if (uid == 0)
var = child_get_env(tmpenv, "SUPATH");
else
var = child_get_env(tmpenv, "PATH");
if (var != NULL)
child_set_env(env, envsize, "PATH", var);
if ((var = child_get_env(tmpenv, "UMASK")) != NULL)
if (sscanf(var, "%5lo", &mask) == 1)
umask((mode_t)mask);
for (i = 0; tmpenv[i] != NULL; i++)
free(tmpenv[i]);
free(tmpenv);
}
#endif /* HAVE_ETC_DEFAULT_LOGIN */
static void
copy_environment_blacklist(char **source, char ***env, u_int *envsize,
const char *blacklist)
{
char *var_name, *var_val;
int i;
if (source == NULL)
return;
for(i = 0; source[i] != NULL; i++) {
var_name = xstrdup(source[i]);
if ((var_val = strstr(var_name, "=")) == NULL) {
free(var_name);
continue;
}
*var_val++ = '\0';
if (blacklist == NULL ||
match_pattern_list(var_name, blacklist, 0) != 1) {
debug3("Copy environment: %s=%s", var_name, var_val);
child_set_env(env, envsize, var_name, var_val);
}
free(var_name);
}
}
void
copy_environment(char **source, char ***env, u_int *envsize)
{
copy_environment_blacklist(source, env, envsize, NULL);
}
static char **
do_setup_env(struct ssh *ssh, Session *s, const char *shell)
{
char buf[256];
size_t n;
u_int i, envsize;
char *ocp, *cp, *value, **env, *laddr;
struct passwd *pw = s->pw;
#if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
char *path = NULL;
#endif
/* Initialize the environment. */
envsize = 100;
env = xcalloc(envsize, sizeof(char *));
env[0] = NULL;
#ifdef HAVE_CYGWIN
/*
* The Windows environment contains some setting which are
* important for a running system. They must not be dropped.
*/
{
char **p;
p = fetch_windows_environment();
copy_environment(p, &env, &envsize);
free_windows_environment(p);
}
#endif
#ifdef GSSAPI
/* Allow any GSSAPI methods that we've used to alter
* the childs environment as they see fit
*/
ssh_gssapi_do_child(&env, &envsize);
#endif
/* Set basic environment. */
for (i = 0; i < s->num_env; i++)
child_set_env(&env, &envsize, s->env[i].name, s->env[i].val);
child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
#ifdef _AIX
child_set_env(&env, &envsize, "LOGIN", pw->pw_name);
#endif
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETPATH) < 0)
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
else
child_set_env(&env, &envsize, "PATH", getenv("PATH"));
#else /* HAVE_LOGIN_CAP */
# ifndef HAVE_CYGWIN
/*
* There's no standard path on Windows. The path contains
* important components pointing to the system directories,
* needed for loading shared libraries. So the path better
* remains intact here.
*/
# ifdef HAVE_ETC_DEFAULT_LOGIN
read_etc_default_login(&env, &envsize, pw->pw_uid);
path = child_get_env(env, "PATH");
# endif /* HAVE_ETC_DEFAULT_LOGIN */
if (path == NULL || *path == '\0') {
child_set_env(&env, &envsize, "PATH",
s->pw->pw_uid == 0 ? SUPERUSER_PATH : _PATH_STDPATH);
}
# endif /* HAVE_CYGWIN */
#endif /* HAVE_LOGIN_CAP */
- snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name);
- child_set_env(&env, &envsize, "MAIL", buf);
+ if (!options.use_pam) {
+ snprintf(buf, sizeof buf, "%.200s/%.50s",
+ _PATH_MAILDIR, pw->pw_name);
+ child_set_env(&env, &envsize, "MAIL", buf);
+ }
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
if (s->term)
child_set_env(&env, &envsize, "TERM", s->term);
if (s->display)
child_set_env(&env, &envsize, "DISPLAY", s->display);
/*
* Since we clear KRB5CCNAME at startup, if it's set now then it
* must have been set by a native authentication method (eg AIX or
* SIA), so copy it to the child.
*/
{
char *cp;
if ((cp = getenv("KRB5CCNAME")) != NULL)
child_set_env(&env, &envsize, "KRB5CCNAME", cp);
}
#ifdef _AIX
{
char *cp;
if ((cp = getenv("AUTHSTATE")) != NULL)
child_set_env(&env, &envsize, "AUTHSTATE", cp);
read_environment_file(&env, &envsize, "/etc/environment",
options.permit_user_env_whitelist);
}
#endif
#ifdef KRB5
if (s->authctxt->krb5_ccname)
child_set_env(&env, &envsize, "KRB5CCNAME",
s->authctxt->krb5_ccname);
#endif
if (auth_sock_name != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
auth_sock_name);
/* Set custom environment options from pubkey authentication. */
if (options.permit_user_env) {
for (n = 0 ; n < auth_opts->nenv; n++) {
ocp = xstrdup(auth_opts->env[n]);
cp = strchr(ocp, '=');
if (*cp == '=') {
*cp = '\0';
/* Apply PermitUserEnvironment whitelist */
if (options.permit_user_env_whitelist == NULL ||
match_pattern_list(ocp,
options.permit_user_env_whitelist, 0) == 1)
child_set_env(&env, &envsize,
ocp, cp + 1);
}
free(ocp);
}
}
/* read $HOME/.ssh/environment. */
if (options.permit_user_env) {
snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
pw->pw_dir);
read_environment_file(&env, &envsize, buf,
options.permit_user_env_whitelist);
}
#ifdef USE_PAM
/*
* Pull in any environment variables that may have
* been set by PAM.
*/
if (options.use_pam) {
char **p;
/*
- * Don't allow SSH_AUTH_INFO variables posted to PAM to leak
- * back into the environment.
+ * Don't allow PAM-internal env vars to leak
+ * back into the session environment.
*/
+#define PAM_ENV_BLACKLIST "SSH_AUTH_INFO*,SSH_CONNECTION*"
p = fetch_pam_child_environment();
- copy_environment_blacklist(p, &env, &envsize, "SSH_AUTH_INFO*");
+ copy_environment_blacklist(p, &env, &envsize,
+ PAM_ENV_BLACKLIST);
free_pam_environment(p);
p = fetch_pam_environment();
- copy_environment_blacklist(p, &env, &envsize, "SSH_AUTH_INFO*");
+ copy_environment_blacklist(p, &env, &envsize,
+ PAM_ENV_BLACKLIST);
free_pam_environment(p);
}
#endif /* USE_PAM */
/* Environment specified by admin */
for (i = 0; i < options.num_setenv; i++) {
cp = xstrdup(options.setenv[i]);
if ((value = strchr(cp, '=')) == NULL) {
/* shouldn't happen; vars are checked in servconf.c */
fatal("Invalid config SetEnv: %s", options.setenv[i]);
}
*value++ = '\0';
child_set_env(&env, &envsize, cp, value);
}
/* SSH_CLIENT deprecated */
snprintf(buf, sizeof buf, "%.50s %d %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
ssh_local_port(ssh));
child_set_env(&env, &envsize, "SSH_CLIENT", buf);
- laddr = get_local_ipaddr(packet_get_connection_in());
+ laddr = get_local_ipaddr(ssh_packet_get_connection_in(ssh));
snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
laddr, ssh_local_port(ssh));
free(laddr);
child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
if (tun_fwd_ifnames != NULL)
child_set_env(&env, &envsize, "SSH_TUNNEL", tun_fwd_ifnames);
if (auth_info_file != NULL)
child_set_env(&env, &envsize, "SSH_USER_AUTH", auth_info_file);
if (s->ttyfd != -1)
child_set_env(&env, &envsize, "SSH_TTY", s->tty);
if (original_command)
child_set_env(&env, &envsize, "SSH_ORIGINAL_COMMAND",
original_command);
if (debug_flag) {
/* dump the environment */
fprintf(stderr, "Environment:\n");
for (i = 0; env[i]; i++)
fprintf(stderr, " %.200s\n", env[i]);
}
return env;
}
/*
* Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
* first in this order).
*/
static void
do_rc_files(struct ssh *ssh, Session *s, const char *shell)
{
FILE *f = NULL;
char cmd[1024];
int do_xauth;
struct stat st;
do_xauth =
s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
if (!s->is_subsystem && options.adm_forced_command == NULL &&
auth_opts->permit_user_rc && options.permit_user_rc &&
stat(_PATH_SSH_USER_RC, &st) >= 0) {
snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
if (debug_flag)
fprintf(stderr, "Running %s\n", cmd);
f = popen(cmd, "w");
if (f) {
if (do_xauth)
fprintf(f, "%s %s\n", s->auth_proto,
s->auth_data);
pclose(f);
} else
fprintf(stderr, "Could not run %s\n",
_PATH_SSH_USER_RC);
} else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
if (debug_flag)
fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
_PATH_SSH_SYSTEM_RC);
f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
if (f) {
if (do_xauth)
fprintf(f, "%s %s\n", s->auth_proto,
s->auth_data);
pclose(f);
} else
fprintf(stderr, "Could not run %s\n",
_PATH_SSH_SYSTEM_RC);
} else if (do_xauth && options.xauth_location != NULL) {
/* Add authority data to .Xauthority if appropriate. */
if (debug_flag) {
fprintf(stderr,
"Running %.500s remove %.100s\n",
options.xauth_location, s->auth_display);
fprintf(stderr,
"%.500s add %.100s %.100s %.100s\n",
options.xauth_location, s->auth_display,
s->auth_proto, s->auth_data);
}
snprintf(cmd, sizeof cmd, "%s -q -",
options.xauth_location);
f = popen(cmd, "w");
if (f) {
fprintf(f, "remove %s\n",
s->auth_display);
fprintf(f, "add %s %s %s\n",
s->auth_display, s->auth_proto,
s->auth_data);
pclose(f);
} else {
fprintf(stderr, "Could not run %s\n",
cmd);
}
}
}
static void
do_nologin(struct passwd *pw)
{
FILE *f = NULL;
char buf[1024], *nl, *def_nl = _PATH_NOLOGIN;
struct stat sb;
#ifdef HAVE_LOGIN_CAP
if (login_getcapbool(lc, "ignorenologin", 0) || pw->pw_uid == 0)
return;
nl = login_getcapstr(lc, "nologin", def_nl, def_nl);
#else
if (pw->pw_uid == 0)
return;
nl = def_nl;
#endif
if (stat(nl, &sb) == -1) {
if (nl != def_nl)
free(nl);
return;
}
/* /etc/nologin exists. Print its contents if we can and exit. */
logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
if ((f = fopen(nl, "r")) != NULL) {
while (fgets(buf, sizeof(buf), f))
fputs(buf, stderr);
fclose(f);
}
exit(254);
}
/*
* Chroot into a directory after checking it for safety: all path components
* must be root-owned directories with strict permissions.
*/
static void
safely_chroot(const char *path, uid_t uid)
{
const char *cp;
char component[PATH_MAX];
struct stat st;
- if (*path != '/')
+ if (!path_absolute(path))
fatal("chroot path does not begin at root");
if (strlen(path) >= sizeof(component))
fatal("chroot path too long");
/*
* Descend the path, checking that each component is a
* root-owned directory with strict permissions.
*/
for (cp = path; cp != NULL;) {
if ((cp = strchr(cp, '/')) == NULL)
strlcpy(component, path, sizeof(component));
else {
cp++;
memcpy(component, path, cp - path);
component[cp - path] = '\0';
}
debug3("%s: checking '%s'", __func__, component);
if (stat(component, &st) != 0)
fatal("%s: stat(\"%s\"): %s", __func__,
component, strerror(errno));
if (st.st_uid != 0 || (st.st_mode & 022) != 0)
fatal("bad ownership or modes for chroot "
- "directory %s\"%s\"",
+ "directory %s\"%s\"",
cp == NULL ? "" : "component ", component);
if (!S_ISDIR(st.st_mode))
fatal("chroot path %s\"%s\" is not a directory",
cp == NULL ? "" : "component ", component);
}
if (chdir(path) == -1)
fatal("Unable to chdir to chroot path \"%s\": "
"%s", path, strerror(errno));
if (chroot(path) == -1)
fatal("chroot(\"%s\"): %s", path, strerror(errno));
if (chdir("/") == -1)
fatal("%s: chdir(/) after chroot: %s",
__func__, strerror(errno));
verbose("Changed root directory to \"%s\"", path);
}
/* Set login name, uid, gid, and groups. */
void
do_setusercontext(struct passwd *pw)
{
char uidstr[32], *chroot_path, *tmp;
platform_setusercontext(pw);
if (platform_privileged_uidswap()) {
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid,
(LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
perror("unable to set user context");
exit(1);
}
#else
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
if (setgid(pw->pw_gid) < 0) {
perror("setgid");
exit(1);
}
/* Initialize the group list. */
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
perror("initgroups");
exit(1);
}
endgrent();
#endif
platform_setusercontext_post_groups(pw);
if (!in_chroot && options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
tmp = tilde_expand_filename(options.chroot_directory,
pw->pw_uid);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
"u", pw->pw_name, "U", uidstr, (char *)NULL);
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
/* Make sure we don't attempt to chroot again */
free(options.chroot_directory);
options.chroot_directory = NULL;
in_chroot = 1;
}
#ifdef HAVE_LOGIN_CAP
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUSER) < 0) {
perror("unable to set user context (setuser)");
exit(1);
}
/*
* FreeBSD's setusercontext() will not apply the user's
* own umask setting unless running with the user's UID.
*/
(void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK);
#else
# ifdef USE_LIBIAF
/*
* In a chroot environment, the set_id() will always fail;
* typically because of the lack of necessary authentication
* services and runtime such as ./usr/lib/libiaf.so,
* ./usr/lib/libpam.so.1, and ./etc/passwd We skip it in the
* internal sftp chroot case. We'll lose auditing and ACLs but
* permanently_set_uid will take care of the rest.
*/
if (!in_chroot && set_id(pw->pw_name) != 0)
fatal("set_id(%s) Failed", pw->pw_name);
# endif /* USE_LIBIAF */
/* Permanently switch to the desired uid. */
permanently_set_uid(pw);
#endif
} else if (options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
fatal("server lacks privileges to chroot to ChrootDirectory");
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
}
static void
do_pwchange(Session *s)
{
fflush(NULL);
fprintf(stderr, "WARNING: Your password has expired.\n");
if (s->ttyfd != -1) {
fprintf(stderr,
"You must change your password now and login again!\n");
#ifdef WITH_SELINUX
setexeccon(NULL);
#endif
#ifdef PASSWD_NEEDS_USERNAME
execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
(char *)NULL);
#else
execl(_PATH_PASSWD_PROG, "passwd", (char *)NULL);
#endif
perror("passwd");
} else {
fprintf(stderr,
"Password change required but no TTY available.\n");
}
exit(1);
}
static void
child_close_fds(struct ssh *ssh)
{
extern int auth_sock;
if (auth_sock != -1) {
close(auth_sock);
auth_sock = -1;
}
- if (packet_get_connection_in() == packet_get_connection_out())
- close(packet_get_connection_in());
+ if (ssh_packet_get_connection_in(ssh) ==
+ ssh_packet_get_connection_out(ssh))
+ close(ssh_packet_get_connection_in(ssh));
else {
- close(packet_get_connection_in());
- close(packet_get_connection_out());
+ close(ssh_packet_get_connection_in(ssh));
+ close(ssh_packet_get_connection_out(ssh));
}
/*
* Close all descriptors related to channels. They will still remain
* open in the parent.
*/
/* XXX better use close-on-exec? -markus */
channel_close_all(ssh);
/*
* Close any extra file descriptors. Note that there may still be
* descriptors left by system functions. They will be closed later.
*/
endpwent();
/*
* Close any extra open file descriptors so that we don't have them
* hanging around in clients. Note that we want to do this after
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
closefrom(STDERR_FILENO + 1);
}
/*
* Performs common processing for the child, such as setting up the
* environment, closing extra file descriptors, setting the user and group
* ids, and executing the command or shell.
*/
#define ARGV_MAX 10
void
do_child(struct ssh *ssh, Session *s, const char *command)
{
extern char **environ;
- char **env;
- char *argv[ARGV_MAX];
+ char **env, *argv[ARGV_MAX], remote_id[512];
const char *shell, *shell0;
struct passwd *pw = s->pw;
int r = 0;
+ sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
+
/* remove hostkey from the child's memory */
destroy_sensitive_data();
- packet_clear_keys();
+ ssh_packet_clear_keys(ssh);
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);
child_close_fds(ssh);
do_pwchange(s);
exit(1);
}
/*
* Login(1) does this as well, and it needs uid 0 for the "-h"
* switch, so we let login(1) to this for us.
*/
#ifdef HAVE_OSF_SIA
session_setup_sia(pw, s->ttyfd == -1 ? NULL : s->tty);
if (!check_quietlogin(s, command))
do_motd();
#else /* HAVE_OSF_SIA */
/* When PAM is enabled we rely on it to do the nologin check */
if (!options.use_pam)
do_nologin(pw);
do_setusercontext(pw);
/*
* PAM session modules in do_setusercontext may have
* generated messages, so if this in an interactive
* login then display them too.
*/
if (!check_quietlogin(s, command))
display_loginmsg();
#endif /* HAVE_OSF_SIA */
#ifdef USE_PAM
if (options.use_pam && !is_pam_session_open()) {
debug3("PAM session not opened, exiting");
display_loginmsg();
exit(254);
}
#endif
/*
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
/*
* Make sure $SHELL points to the shell from the password file,
* even if shell is overridden from login.conf
*/
env = do_setup_env(ssh, s, shell);
#ifdef HAVE_LOGIN_CAP
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
#endif
/*
* Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important
* that we do not shutdown it. Note that the descriptors cannot be
* closed before building the environment, as we call
* ssh_remote_ipaddr there.
*/
child_close_fds(ssh);
/*
* Must take new environment into use so that .ssh/rc,
* /etc/ssh/sshrc and xauth are run in the proper environment.
*/
environ = env;
#if defined(KRB5) && defined(USE_AFS)
/*
* At this point, we check to see if AFS is active and if we have
* a valid Kerberos 5 TGT. If so, it seems like a good idea to see
* if we can (and need to) extend the ticket into an AFS token. If
* we don't do this, we run into potential problems if the user's
* home directory is in AFS and it's not world-readable.
*/
if (options.kerberos_get_afs_token && k_hasafs() &&
(s->authctxt->krb5_ctx != NULL)) {
char cell[64];
debug("Getting AFS token");
k_setpag();
if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
krb5_afslog(s->authctxt->krb5_ctx,
s->authctxt->krb5_fwd_ccache, cell, NULL);
krb5_afslog_home(s->authctxt->krb5_ctx,
s->authctxt->krb5_fwd_ccache, NULL, NULL, pw->pw_dir);
}
#endif
/* Change current directory to the user's home directory. */
if (chdir(pw->pw_dir) < 0) {
/* Suppress missing homedir warning for chroot case */
#ifdef HAVE_LOGIN_CAP
r = login_getcapbool(lc, "requirehome", 0);
#endif
if (r || !in_chroot) {
fprintf(stderr, "Could not chdir to home "
"directory %s: %s\n", pw->pw_dir,
strerror(errno));
}
if (r)
exit(1);
}
closefrom(STDERR_FILENO + 1);
do_rc_files(ssh, s, shell);
/* restore SIGPIPE for child */
signal(SIGPIPE, SIG_DFL);
if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) {
+ error("Connection from %s: refusing non-sftp session",
+ remote_id);
printf("This service allows sftp connections only.\n");
fflush(NULL);
exit(1);
} else if (s->is_subsystem == SUBSYSTEM_INT_SFTP) {
extern int optind, optreset;
int i;
char *p, *args;
setproctitle("%s@%s", s->pw->pw_name, INTERNAL_SFTP_NAME);
args = xstrdup(command ? command : "sftp-server");
for (i = 0, (p = strtok(args, " ")); p; (p = strtok(NULL, " ")))
if (i < ARGV_MAX - 1)
argv[i++] = p;
argv[i] = NULL;
optind = optreset = 1;
__progname = argv[0];
#ifdef WITH_SELINUX
ssh_selinux_change_context("sftpd_t");
#endif
exit(sftp_server_main(i, argv, s->pw));
}
fflush(NULL);
/* Get the last component of the shell name. */
if ((shell0 = strrchr(shell, '/')) != NULL)
shell0++;
else
shell0 = shell;
/*
* If we have no command, execute the shell. In this case, the shell
* name to be passed in argv[0] is preceded by '-' to indicate that
* this is a login shell.
*/
if (!command) {
char argv0[256];
/* Start the shell. Set initial character to '-'. */
argv0[0] = '-';
if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
>= sizeof(argv0) - 1) {
errno = EINVAL;
perror(shell);
exit(1);
}
/* Execute the shell. */
argv[0] = argv0;
argv[1] = NULL;
execve(shell, argv, env);
/* Executing the shell failed. */
perror(shell);
exit(1);
}
/*
* Execute the command using the user's shell. This uses the -c
* option to execute the command.
*/
argv[0] = (char *) shell0;
argv[1] = "-c";
argv[2] = (char *) command;
argv[3] = NULL;
execve(shell, argv, env);
perror(shell);
exit(1);
}
void
session_unused(int id)
{
debug3("%s: session id %d unused", __func__, id);
if (id >= options.max_sessions ||
id >= sessions_nalloc) {
fatal("%s: insane session id %d (max %d nalloc %d)",
__func__, id, options.max_sessions, sessions_nalloc);
}
memset(&sessions[id], 0, sizeof(*sessions));
sessions[id].self = id;
sessions[id].used = 0;
sessions[id].chanid = -1;
sessions[id].ptyfd = -1;
sessions[id].ttyfd = -1;
sessions[id].ptymaster = -1;
sessions[id].x11_chanids = NULL;
sessions[id].next_unused = sessions_first_unused;
sessions_first_unused = id;
}
Session *
session_new(void)
{
Session *s, *tmp;
if (sessions_first_unused == -1) {
if (sessions_nalloc >= options.max_sessions)
return NULL;
debug2("%s: allocate (allocated %d max %d)",
__func__, sessions_nalloc, options.max_sessions);
tmp = xrecallocarray(sessions, sessions_nalloc,
sessions_nalloc + 1, sizeof(*sessions));
if (tmp == NULL) {
error("%s: cannot allocate %d sessions",
__func__, sessions_nalloc + 1);
return NULL;
}
sessions = tmp;
session_unused(sessions_nalloc++);
}
if (sessions_first_unused >= sessions_nalloc ||
sessions_first_unused < 0) {
fatal("%s: insane first_unused %d max %d nalloc %d",
__func__, sessions_first_unused, options.max_sessions,
sessions_nalloc);
}
s = &sessions[sessions_first_unused];
if (s->used) {
fatal("%s: session %d already used",
__func__, sessions_first_unused);
}
sessions_first_unused = s->next_unused;
s->used = 1;
s->next_unused = -1;
debug("session_new: session %d", s->self);
return s;
}
static void
session_dump(void)
{
int i;
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
debug("dump: used %d next_unused %d session %d %p "
"channel %d pid %ld",
s->used,
s->next_unused,
s->self,
s,
s->chanid,
(long)s->pid);
}
}
int
session_open(Authctxt *authctxt, int chanid)
{
Session *s = session_new();
debug("session_open: channel %d", chanid);
if (s == NULL) {
error("no more sessions");
return 0;
}
s->authctxt = authctxt;
s->pw = authctxt->pw;
if (s->pw == NULL || !authctxt->valid)
fatal("no user for session %d", s->self);
debug("session_open: session %d: link with channel %d", s->self, chanid);
s->chanid = chanid;
return 1;
}
Session *
session_by_tty(char *tty)
{
int i;
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
debug("session_by_tty: session %d tty %s", i, tty);
return s;
}
}
debug("session_by_tty: unknown tty %.100s", tty);
session_dump();
return NULL;
}
static Session *
session_by_channel(int id)
{
int i;
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->used && s->chanid == id) {
debug("session_by_channel: session %d channel %d",
i, id);
return s;
}
}
debug("session_by_channel: unknown channel %d", id);
session_dump();
return NULL;
}
static Session *
session_by_x11_channel(int id)
{
int i, j;
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->x11_chanids == NULL || !s->used)
continue;
for (j = 0; s->x11_chanids[j] != -1; j++) {
if (s->x11_chanids[j] == id) {
debug("session_by_x11_channel: session %d "
"channel %d", s->self, id);
return s;
}
}
}
debug("session_by_x11_channel: unknown channel %d", id);
session_dump();
return NULL;
}
static Session *
session_by_pid(pid_t pid)
{
int i;
debug("session_by_pid: pid %ld", (long)pid);
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->used && s->pid == pid)
return s;
}
error("session_by_pid: unknown pid %ld", (long)pid);
session_dump();
return NULL;
}
static int
session_window_change_req(struct ssh *ssh, Session *s)
{
- s->col = packet_get_int();
- s->row = packet_get_int();
- s->xpixel = packet_get_int();
- s->ypixel = packet_get_int();
- packet_check_eom();
+ int r;
+
+ if ((r = sshpkt_get_u32(ssh, &s->col)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->row)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->ypixel)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
return 1;
}
static int
session_pty_req(struct ssh *ssh, Session *s)
{
- u_int len;
+ int r;
if (!auth_opts->permit_pty_flag || !options.permit_tty) {
debug("Allocating a pty not permitted for this connection.");
return 0;
}
if (s->ttyfd != -1) {
- packet_disconnect("Protocol error: you already have a pty.");
+ ssh_packet_disconnect(ssh, "Protocol error: you already have a pty.");
return 0;
}
- s->term = packet_get_string(&len);
- s->col = packet_get_int();
- s->row = packet_get_int();
- s->xpixel = packet_get_int();
- s->ypixel = packet_get_int();
+ if ((r = sshpkt_get_cstring(ssh, &s->term, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->col)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->row)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->xpixel)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->ypixel)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (strcmp(s->term, "") == 0) {
free(s->term);
s->term = NULL;
}
/* Allocate a pty and open it. */
debug("Allocating pty.");
if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
sizeof(s->tty)))) {
free(s->term);
s->term = NULL;
s->ptyfd = -1;
s->ttyfd = -1;
error("session_pty_req: session %d alloc failed", s->self);
return 0;
}
debug("session_pty_req: session %d alloc %s", s->self, s->tty);
ssh_tty_parse_modes(ssh, s->ttyfd);
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+
if (!use_privsep)
pty_setowner(s->pw, s->tty);
/* Set window size from the packet. */
pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
- packet_check_eom();
session_proctitle(s);
return 1;
}
static int
session_subsystem_req(struct ssh *ssh, Session *s)
{
struct stat st;
- u_int len;
- int success = 0;
+ int r, success = 0;
char *prog, *cmd;
u_int i;
- s->subsys = packet_get_string(&len);
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &s->subsys, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
debug2("subsystem request for %.100s by user %s", s->subsys,
s->pw->pw_name);
for (i = 0; i < options.num_subsystems; i++) {
if (strcmp(s->subsys, options.subsystem_name[i]) == 0) {
prog = options.subsystem_command[i];
cmd = options.subsystem_args[i];
if (strcmp(INTERNAL_SFTP_NAME, prog) == 0) {
s->is_subsystem = SUBSYSTEM_INT_SFTP;
debug("subsystem: %s", prog);
} else {
if (stat(prog, &st) < 0)
debug("subsystem: cannot stat %s: %s",
prog, strerror(errno));
s->is_subsystem = SUBSYSTEM_EXT;
debug("subsystem: exec() %s", cmd);
}
success = do_exec(ssh, s, cmd) == 0;
break;
}
}
if (!success)
logit("subsystem request for %.100s by user %s failed, "
"subsystem not found", s->subsys, s->pw->pw_name);
return success;
}
static int
session_x11_req(struct ssh *ssh, Session *s)
{
- int success;
+ int r, success;
+ u_char single_connection = 0;
if (s->auth_proto != NULL || s->auth_data != NULL) {
error("session_x11_req: session %d: "
"x11 forwarding already active", s->self);
return 0;
}
- s->single_connection = packet_get_char();
- s->auth_proto = packet_get_string(NULL);
- s->auth_data = packet_get_string(NULL);
- s->screen = packet_get_int();
- packet_check_eom();
+ if ((r = sshpkt_get_u8(ssh, &single_connection)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &s->auth_proto, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &s->auth_data, NULL)) != 0 ||
+ (r = sshpkt_get_u32(ssh, &s->screen)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+
+ s->single_connection = single_connection;
if (xauth_valid_string(s->auth_proto) &&
xauth_valid_string(s->auth_data))
success = session_setup_x11fwd(ssh, s);
else {
success = 0;
error("Invalid X11 forwarding data");
}
if (!success) {
free(s->auth_proto);
free(s->auth_data);
s->auth_proto = NULL;
s->auth_data = NULL;
}
return success;
}
static int
session_shell_req(struct ssh *ssh, Session *s)
{
- packet_check_eom();
+ int r;
+
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
return do_exec(ssh, s, NULL) == 0;
}
static int
session_exec_req(struct ssh *ssh, Session *s)
{
- u_int len, success;
+ u_int success;
+ int r;
+ char *command = NULL;
+
+ if ((r = sshpkt_get_cstring(ssh, &command, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
- char *command = packet_get_string(&len);
- packet_check_eom();
success = do_exec(ssh, s, command) == 0;
free(command);
return success;
}
static int
session_break_req(struct ssh *ssh, Session *s)
{
+ int r;
- packet_get_int(); /* ignored */
- packet_check_eom();
+ if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* ignore */
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (s->ptymaster == -1 || tcsendbreak(s->ptymaster, 0) < 0)
return 0;
return 1;
}
static int
session_env_req(struct ssh *ssh, Session *s)
{
char *name, *val;
- u_int name_len, val_len, i;
+ u_int i;
+ int r;
- name = packet_get_cstring(&name_len);
- val = packet_get_cstring(&val_len);
- packet_check_eom();
+ if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, &val, NULL)) != 0 ||
+ (r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
/* Don't set too many environment variables */
if (s->num_env > 128) {
debug2("Ignoring env request %s: too many env vars", name);
goto fail;
}
for (i = 0; i < options.num_accept_env; i++) {
if (match_pattern(name, options.accept_env[i])) {
debug2("Setting env %d: %s=%s", s->num_env, name, val);
s->env = xrecallocarray(s->env, s->num_env,
s->num_env + 1, sizeof(*s->env));
s->env[s->num_env].name = name;
s->env[s->num_env].val = val;
s->num_env++;
return (1);
}
}
debug2("Ignoring env request %s: disallowed name", name);
fail:
free(name);
free(val);
return (0);
}
/*
* Conversion of signals from ssh channel request names.
* Subset of signals from RFC 4254 section 6.10C, with SIGINFO as
* local extension.
*/
static int
name2sig(char *name)
{
#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x
SSH_SIG(HUP);
SSH_SIG(INT);
SSH_SIG(KILL);
SSH_SIG(QUIT);
SSH_SIG(TERM);
SSH_SIG(USR1);
SSH_SIG(USR2);
#undef SSH_SIG
#ifdef SIGINFO
if (strcmp(name, "INFO@openssh.com") == 0)
return SIGINFO;
#endif
return -1;
}
static int
session_signal_req(struct ssh *ssh, Session *s)
{
char *signame = NULL;
int r, sig, success = 0;
if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
error("%s: parse packet: %s", __func__, ssh_err(r));
goto out;
}
if ((sig = name2sig(signame)) == -1) {
error("%s: unsupported signal \"%s\"", __func__, signame);
goto out;
}
if (s->pid <= 0) {
error("%s: no pid for session %d", __func__, s->self);
goto out;
}
if (s->forced || s->is_subsystem) {
error("%s: refusing to send signal %s to %s session", __func__,
signame, s->forced ? "forced-command" : "subsystem");
goto out;
}
if (!use_privsep || mm_is_monitor()) {
error("%s: session signalling requires privilege separation",
__func__);
goto out;
}
debug("%s: signal %s, killpg(%ld, %d)", __func__, signame,
(long)s->pid, sig);
temporarily_use_uid(s->pw);
r = killpg(s->pid, sig);
restore_uid();
if (r != 0) {
error("%s: killpg(%ld, %d): %s", __func__, (long)s->pid,
sig, strerror(errno));
goto out;
}
/* success */
success = 1;
out:
free(signame);
return success;
}
static int
session_auth_agent_req(struct ssh *ssh, Session *s)
{
static int called = 0;
+ int r;
- packet_check_eom();
+ if ((r = sshpkt_get_end(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (!auth_opts->permit_agent_forwarding_flag ||
!options.allow_agent_forwarding) {
debug("%s: agent forwarding disabled", __func__);
return 0;
}
if (called) {
return 0;
} else {
called = 1;
return auth_input_request_forwarding(ssh, s->pw);
}
}
int
session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype)
{
int success = 0;
Session *s;
if ((s = session_by_channel(c->self)) == NULL) {
logit("%s: no session %d req %.100s", __func__, c->self, rtype);
return 0;
}
debug("%s: session %d req %s", __func__, s->self, rtype);
/*
* a session is in LARVAL state until a shell, a command
* or a subsystem is executed
*/
if (c->type == SSH_CHANNEL_LARVAL) {
if (strcmp(rtype, "shell") == 0) {
success = session_shell_req(ssh, s);
} else if (strcmp(rtype, "exec") == 0) {
success = session_exec_req(ssh, s);
} else if (strcmp(rtype, "pty-req") == 0) {
success = session_pty_req(ssh, s);
} else if (strcmp(rtype, "x11-req") == 0) {
success = session_x11_req(ssh, s);
} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
success = session_auth_agent_req(ssh, s);
} else if (strcmp(rtype, "subsystem") == 0) {
success = session_subsystem_req(ssh, s);
} else if (strcmp(rtype, "env") == 0) {
success = session_env_req(ssh, s);
}
}
if (strcmp(rtype, "window-change") == 0) {
success = session_window_change_req(ssh, s);
} else if (strcmp(rtype, "break") == 0) {
success = session_break_req(ssh, s);
} else if (strcmp(rtype, "signal") == 0) {
success = session_signal_req(ssh, s);
}
return success;
}
void
session_set_fds(struct ssh *ssh, Session *s,
int fdin, int fdout, int fderr, int ignore_fderr, int is_tty)
{
/*
* now that have a child and a pipe to the child,
* we can activate our channel and register the fd's
*/
if (s->chanid == -1)
fatal("no channel for session %d", s->self);
channel_set_fds(ssh, s->chanid,
fdout, fdin, fderr,
ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1, is_tty, CHAN_SES_WINDOW_DEFAULT);
}
/*
* Function to perform pty cleanup. Also called if we get aborted abnormally
* (e.g., due to a dropped connection).
*/
void
session_pty_cleanup2(Session *s)
{
if (s == NULL) {
error("%s: no session", __func__);
return;
}
if (s->ttyfd == -1)
return;
debug("%s: session %d release %s", __func__, s->self, s->tty);
/* Record that the user has logged out. */
if (s->pid != 0)
record_logout(s->pid, s->tty, s->pw->pw_name);
/* Release the pseudo-tty. */
if (getuid() == 0)
pty_release(s->tty);
/*
* Close the server side of the socket pairs. We must do this after
* the pty cleanup, so that another process doesn't get this pty
* while we're still cleaning up.
*/
if (s->ptymaster != -1 && close(s->ptymaster) < 0)
error("close(s->ptymaster/%d): %s",
s->ptymaster, strerror(errno));
/* unlink pty from session */
s->ttyfd = -1;
}
void
session_pty_cleanup(Session *s)
{
PRIVSEP(session_pty_cleanup2(s));
}
static char *
sig2name(int sig)
{
#define SSH_SIG(x) if (sig == SIG ## x) return #x
SSH_SIG(ABRT);
SSH_SIG(ALRM);
SSH_SIG(FPE);
SSH_SIG(HUP);
SSH_SIG(ILL);
SSH_SIG(INT);
SSH_SIG(KILL);
SSH_SIG(PIPE);
SSH_SIG(QUIT);
SSH_SIG(SEGV);
SSH_SIG(TERM);
SSH_SIG(USR1);
SSH_SIG(USR2);
#undef SSH_SIG
return "SIG@openssh.com";
}
static void
session_close_x11(struct ssh *ssh, int id)
{
Channel *c;
if ((c = channel_by_id(ssh, id)) == NULL) {
debug("%s: x11 channel %d missing", __func__, id);
} else {
/* Detach X11 listener */
debug("%s: detach x11 channel %d", __func__, id);
channel_cancel_cleanup(ssh, id);
if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_mark_dead(ssh, c);
}
}
static void
session_close_single_x11(struct ssh *ssh, int id, void *arg)
{
Session *s;
u_int i;
debug3("%s: channel %d", __func__, id);
channel_cancel_cleanup(ssh, id);
if ((s = session_by_x11_channel(id)) == NULL)
fatal("%s: no x11 channel %d", __func__, id);
for (i = 0; s->x11_chanids[i] != -1; i++) {
debug("%s: session %d: closing channel %d",
__func__, s->self, s->x11_chanids[i]);
/*
* The channel "id" is already closing, but make sure we
* close all of its siblings.
*/
if (s->x11_chanids[i] != id)
session_close_x11(ssh, s->x11_chanids[i]);
}
free(s->x11_chanids);
s->x11_chanids = NULL;
free(s->display);
s->display = NULL;
free(s->auth_proto);
s->auth_proto = NULL;
free(s->auth_data);
s->auth_data = NULL;
free(s->auth_display);
s->auth_display = NULL;
}
static void
session_exit_message(struct ssh *ssh, Session *s, int status)
{
Channel *c;
+ int r;
if ((c = channel_lookup(ssh, s->chanid)) == NULL)
fatal("%s: session %d: no channel %d",
__func__, s->self, s->chanid);
debug("%s: session %d channel %d pid %ld",
__func__, s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) {
channel_request_start(ssh, s->chanid, "exit-status", 0);
- packet_put_int(WEXITSTATUS(status));
- packet_send();
+ if ((r = sshpkt_put_u32(ssh, WEXITSTATUS(status))) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: exit reply", __func__);
} else if (WIFSIGNALED(status)) {
channel_request_start(ssh, s->chanid, "exit-signal", 0);
- packet_put_cstring(sig2name(WTERMSIG(status)));
-#ifdef WCOREDUMP
- packet_put_char(WCOREDUMP(status)? 1 : 0);
-#else /* WCOREDUMP */
- packet_put_char(0);
-#endif /* WCOREDUMP */
- packet_put_cstring("");
- packet_put_cstring("");
- packet_send();
+#ifndef WCOREDUMP
+# define WCOREDUMP(x) (0)
+#endif
+ if ((r = sshpkt_put_cstring(ssh, sig2name(WTERMSIG(status)))) != 0 ||
+ (r = sshpkt_put_u8(ssh, WCOREDUMP(status)? 1 : 0)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: exit reply", __func__);
} else {
/* Some weird exit cause. Just exit. */
- packet_disconnect("wait returned status %04x.", status);
+ ssh_packet_disconnect(ssh, "wait returned status %04x.", status);
}
/* disconnect channel */
debug("%s: release channel %d", __func__, s->chanid);
/*
* Adjust cleanup callback attachment to send close messages when
* the channel gets EOF. The session will be then be closed
* by session_close_by_channel when the childs close their fds.
*/
channel_register_cleanup(ssh, c->self, session_close_by_channel, 1);
/*
* emulate a write failure with 'chan_write_failed', nobody will be
* interested in data we write.
* Note that we must not call 'chan_read_failed', since there could
* be some more data waiting in the pipe.
*/
if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_write_failed(ssh, c);
}
void
session_close(struct ssh *ssh, Session *s)
{
u_int i;
verbose("Close session: user %s from %.200s port %d id %d",
s->pw->pw_name,
ssh_remote_ipaddr(ssh),
ssh_remote_port(ssh),
s->self);
if (s->ttyfd != -1)
session_pty_cleanup(s);
free(s->term);
free(s->display);
free(s->x11_chanids);
free(s->auth_display);
free(s->auth_data);
free(s->auth_proto);
free(s->subsys);
if (s->env != NULL) {
for (i = 0; i < s->num_env; i++) {
free(s->env[i].name);
free(s->env[i].val);
}
free(s->env);
}
session_proctitle(s);
session_unused(s->self);
}
void
session_close_by_pid(struct ssh *ssh, pid_t pid, int status)
{
Session *s = session_by_pid(pid);
if (s == NULL) {
debug("%s: no session for pid %ld", __func__, (long)pid);
return;
}
if (s->chanid != -1)
session_exit_message(ssh, s, status);
if (s->ttyfd != -1)
session_pty_cleanup(s);
s->pid = 0;
}
/*
* this is called when a channel dies before
* the session 'child' itself dies
*/
void
session_close_by_channel(struct ssh *ssh, int id, void *arg)
{
Session *s = session_by_channel(id);
u_int i;
if (s == NULL) {
debug("%s: no session for id %d", __func__, id);
return;
}
debug("%s: channel %d child %ld", __func__, id, (long)s->pid);
if (s->pid != 0) {
debug("%s: channel %d: has child, ttyfd %d",
__func__, id, s->ttyfd);
/*
* delay detach of session, but release pty, since
* the fd's to the child are already closed
*/
if (s->ttyfd != -1)
session_pty_cleanup(s);
return;
}
/* detach by removing callback */
channel_cancel_cleanup(ssh, s->chanid);
/* Close any X11 listeners associated with this session */
if (s->x11_chanids != NULL) {
for (i = 0; s->x11_chanids[i] != -1; i++) {
session_close_x11(ssh, s->x11_chanids[i]);
s->x11_chanids[i] = -1;
}
}
s->chanid = -1;
session_close(ssh, s);
}
void
session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *))
{
int i;
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->used) {
if (closefunc != NULL)
closefunc(s);
else
session_close(ssh, s);
}
}
}
static char *
session_tty_list(void)
{
static char buf[1024];
int i;
char *cp;
buf[0] = '\0';
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
if (s->used && s->ttyfd != -1) {
if (strncmp(s->tty, "/dev/", 5) != 0) {
cp = strrchr(s->tty, '/');
cp = (cp == NULL) ? s->tty : cp + 1;
} else
cp = s->tty + 5;
if (buf[0] != '\0')
strlcat(buf, ",", sizeof buf);
strlcat(buf, cp, sizeof buf);
}
}
if (buf[0] == '\0')
strlcpy(buf, "notty", sizeof buf);
return buf;
}
void
session_proctitle(Session *s)
{
if (s->pw == NULL)
error("no user for session %d", s->self);
else
setproctitle("%s@%s", s->pw->pw_name, session_tty_list());
}
int
session_setup_x11fwd(struct ssh *ssh, Session *s)
{
struct stat st;
char display[512], auth_display[512];
char hostname[NI_MAXHOST];
u_int i;
if (!auth_opts->permit_x11_forwarding_flag) {
- packet_send_debug("X11 forwarding disabled by key options.");
+ ssh_packet_send_debug(ssh, "X11 forwarding disabled by key options.");
return 0;
}
if (!options.x11_forwarding) {
debug("X11 forwarding disabled in server configuration file.");
return 0;
}
if (options.xauth_location == NULL ||
(stat(options.xauth_location, &st) == -1)) {
- packet_send_debug("No xauth program; cannot forward X11.");
+ ssh_packet_send_debug(ssh, "No xauth program; cannot forward X11.");
return 0;
}
if (s->display != NULL) {
debug("X11 display already set.");
return 0;
}
if (x11_create_display_inet(ssh, options.x11_display_offset,
options.x11_use_localhost, s->single_connection,
&s->display_number, &s->x11_chanids) == -1) {
debug("x11_create_display_inet failed.");
return 0;
}
for (i = 0; s->x11_chanids[i] != -1; i++) {
channel_register_cleanup(ssh, s->x11_chanids[i],
session_close_single_x11, 0);
}
/* Set up a suitable value for the DISPLAY variable. */
if (gethostname(hostname, sizeof(hostname)) < 0)
fatal("gethostname: %.100s", strerror(errno));
/*
* auth_display must be used as the displayname when the
* authorization entry is added with xauth(1). This will be
* different than the DISPLAY string for localhost displays.
*/
if (options.x11_use_localhost) {
snprintf(display, sizeof display, "localhost:%u.%u",
s->display_number, s->screen);
snprintf(auth_display, sizeof auth_display, "unix:%u.%u",
s->display_number, s->screen);
s->display = xstrdup(display);
s->auth_display = xstrdup(auth_display);
} else {
#ifdef IPADDR_IN_DISPLAY
struct hostent *he;
struct in_addr my_addr;
he = gethostbyname(hostname);
if (he == NULL) {
error("Can't get IP address for X11 DISPLAY.");
- packet_send_debug("Can't get IP address for X11 DISPLAY.");
+ ssh_packet_send_debug(ssh, "Can't get IP address for X11 DISPLAY.");
return 0;
}
memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
snprintf(display, sizeof display, "%.50s:%u.%u", inet_ntoa(my_addr),
s->display_number, s->screen);
#else
snprintf(display, sizeof display, "%.400s:%u.%u", hostname,
s->display_number, s->screen);
#endif
s->display = xstrdup(display);
s->auth_display = xstrdup(display);
}
return 1;
}
static void
do_authenticated2(struct ssh *ssh, Authctxt *authctxt)
{
server_loop2(ssh, authctxt);
}
void
do_cleanup(struct ssh *ssh, Authctxt *authctxt)
{
static int called = 0;
debug("do_cleanup");
/* no cleanup if we're in the child for login shell */
if (is_child)
return;
/* avoid double cleanup */
if (called)
return;
called = 1;
if (authctxt == NULL)
return;
#ifdef USE_PAM
if (options.use_pam) {
sshpam_cleanup();
sshpam_thread_cleanup();
}
#endif
if (!authctxt->authenticated)
return;
#ifdef KRB5
if (options.kerberos_ticket_cleanup &&
authctxt->krb5_ctx)
krb5_cleanup_proc(authctxt);
#endif
#ifdef GSSAPI
if (options.gss_cleanup_creds)
ssh_gssapi_cleanup_creds();
#endif
/* remove agent socket */
auth_sock_cleanup_proc(authctxt->pw);
/* remove userauth info */
if (auth_info_file != NULL) {
temporarily_use_uid(authctxt->pw);
unlink(auth_info_file);
restore_uid();
free(auth_info_file);
auth_info_file = NULL;
}
/*
* Cleanup ptys/utmp only if privsep is disabled,
* or if running in monitor.
*/
if (!use_privsep || mm_is_monitor())
session_destroy_all(ssh, session_pty_cleanup2);
}
/* Return a name for the remote host that fits inside utmp_size */
const char *
session_get_remote_name_or_ip(struct ssh *ssh, u_int utmp_size, int use_dns)
{
const char *remote = "";
if (utmp_size > 0)
remote = auth_get_canonical_hostname(ssh, use_dns);
if (utmp_size == 0 || strlen(remote) > utmp_size)
remote = ssh_remote_ipaddr(ssh);
return remote;
}
diff --git a/sftp-client.c b/sftp-client.c
index 4986d6d8d291..73e3c2f53c56 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,1920 +1,1956 @@
-/* $OpenBSD: sftp-client.c,v 1.130 2018/07/31 03:07:24 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.133 2019/01/24 16:52:17 dtucker Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* XXX: memleaks */
/* XXX: signed vs unsigned */
/* XXX: remove all logging, only return status codes */
/* XXX: copy between two remote sites */
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#include "openbsd-compat/sys-queue.h"
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/uio.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "xmalloc.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "log.h"
#include "atomicio.h"
#include "progressmeter.h"
#include "misc.h"
#include "utf8.h"
#include "sftp.h"
#include "sftp-common.h"
#include "sftp-client.h"
extern volatile sig_atomic_t interrupted;
extern int showprogress;
/* Minimum amount of data to read at a time */
#define MIN_READ_SIZE 512
/* Maximum depth to descend in directory trees */
#define MAX_DIR_DEPTH 64
/* Directory separator characters */
#ifdef HAVE_CYGWIN
# define SFTP_DIRECTORY_CHARS "/\\"
#else /* HAVE_CYGWIN */
# define SFTP_DIRECTORY_CHARS "/"
#endif /* HAVE_CYGWIN */
struct sftp_conn {
int fd_in;
int fd_out;
u_int transfer_buflen;
u_int num_requests;
u_int version;
u_int msg_id;
#define SFTP_EXT_POSIX_RENAME 0x00000001
#define SFTP_EXT_STATVFS 0x00000002
#define SFTP_EXT_FSTATVFS 0x00000004
#define SFTP_EXT_HARDLINK 0x00000008
#define SFTP_EXT_FSYNC 0x00000010
+#define SFTP_EXT_LSETSTAT 0x00000020
u_int exts;
u_int64_t limit_kbps;
struct bwlimit bwlimit_in, bwlimit_out;
};
static u_char *
get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
/* ARGSUSED */
static int
sftpio(void *_bwlimit, size_t amount)
{
struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
- bandwidth_limit(bwlimit, amount);
+ refresh_progress_meter(0);
+ if (bwlimit != NULL)
+ bandwidth_limit(bwlimit, amount);
return 0;
}
static void
send_msg(struct sftp_conn *conn, struct sshbuf *m)
{
u_char mlen[4];
struct iovec iov[2];
if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
fatal("Outbound message too long %zu", sshbuf_len(m));
/* Send length first */
put_u32(mlen, sshbuf_len(m));
iov[0].iov_base = mlen;
iov[0].iov_len = sizeof(mlen);
iov[1].iov_base = (u_char *)sshbuf_ptr(m);
iov[1].iov_len = sshbuf_len(m);
- if (atomiciov6(writev, conn->fd_out, iov, 2,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
+ if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
sshbuf_len(m) + sizeof(mlen))
fatal("Couldn't send packet: %s", strerror(errno));
sshbuf_reset(m);
}
static void
get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
{
u_int msg_len;
u_char *p;
int r;
if ((r = sshbuf_reserve(m, 4, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (atomicio6(read, conn->fd_in, p, 4,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
+ if (atomicio6(read, conn->fd_in, p, 4, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
if (errno == EPIPE || errno == ECONNRESET)
fatal("Connection closed");
else
fatal("Couldn't read packet: %s", strerror(errno));
}
if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (msg_len > SFTP_MAX_MSG_LENGTH) {
do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
"Received message too long %u", msg_len);
fatal("Ensure the remote shell produces no output "
"for non-interactive sessions.");
}
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (atomicio6(read, conn->fd_in, p, msg_len,
- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
+ if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
!= msg_len) {
if (errno == EPIPE)
fatal("Connection closed");
else
fatal("Read packet: %s", strerror(errno));
}
}
static void
get_msg(struct sftp_conn *conn, struct sshbuf *m)
{
get_msg_extended(conn, m, 0);
}
static void
send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
u_int len)
{
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, code)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, s, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
sshbuf_free(msg);
}
static void
send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
const void *s, u_int len, Attrib *a)
{
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, code)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, s, len)) != 0 ||
(r = encode_attrib(msg, a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
sshbuf_free(msg);
}
static u_int
get_status(struct sftp_conn *conn, u_int expected_id)
{
struct sshbuf *msg;
u_char type;
u_int id, status;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type != SSH2_FXP_STATUS)
fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
SSH2_FXP_STATUS, type);
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
debug3("SSH2_FXP_STATUS %u", status);
return status;
}
static u_char *
get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
const char *errfmt, ...)
{
struct sshbuf *msg;
u_int id, status;
u_char type;
u_char *handle;
char errmsg[256];
va_list args;
int r;
va_start(args, errfmt);
if (errfmt != NULL)
vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
va_end(args);
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (id != expected_id)
fatal("%s: ID mismatch (%u != %u)",
errfmt == NULL ? __func__ : errmsg, id, expected_id);
if (type == SSH2_FXP_STATUS) {
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (errfmt != NULL)
error("%s: %s", errmsg, fx2txt(status));
sshbuf_free(msg);
return(NULL);
} else if (type != SSH2_FXP_HANDLE)
fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
return handle;
}
static Attrib *
get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
{
struct sshbuf *msg;
u_int id;
u_char type;
int r;
static Attrib a;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("Received stat reply T:%u I:%u", type, id);
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (quiet)
debug("Couldn't stat remote file: %s", fx2txt(status));
else
error("Couldn't stat remote file: %s", fx2txt(status));
sshbuf_free(msg);
return(NULL);
} else if (type != SSH2_FXP_ATTRS) {
fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
SSH2_FXP_ATTRS, type);
}
if ((r = decode_attrib(msg, &a)) != 0) {
error("%s: couldn't decode attrib: %s", __func__, ssh_err(r));
sshbuf_free(msg);
return NULL;
}
sshbuf_free(msg);
return &a;
}
static int
get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
u_int expected_id, int quiet)
{
struct sshbuf *msg;
u_char type;
u_int id;
u_int64_t flag;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("Received statvfs reply T:%u I:%u", type, id);
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (quiet)
debug("Couldn't statvfs: %s", fx2txt(status));
else
error("Couldn't statvfs: %s", fx2txt(status));
sshbuf_free(msg);
return -1;
} else if (type != SSH2_FXP_EXTENDED_REPLY) {
fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
SSH2_FXP_EXTENDED_REPLY, type);
}
memset(st, 0, sizeof(*st));
if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
(r = sshbuf_get_u64(msg, &flag)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
sshbuf_free(msg);
return 0;
}
struct sftp_conn *
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
u_int64_t limit_kbps)
{
u_char type;
struct sshbuf *msg;
struct sftp_conn *ret;
int r;
ret = xcalloc(1, sizeof(*ret));
ret->msg_id = 1;
ret->fd_in = fd_in;
ret->fd_out = fd_out;
ret->transfer_buflen = transfer_buflen;
ret->num_requests = num_requests;
ret->exts = 0;
ret->limit_kbps = 0;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
(r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(ret, msg);
sshbuf_reset(msg);
get_msg_extended(ret, msg, 1);
/* Expecting a VERSION reply */
if ((r = sshbuf_get_u8(msg, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (type != SSH2_FXP_VERSION) {
error("Invalid packet back from SSH2_FXP_INIT (type %u)",
type);
sshbuf_free(msg);
free(ret);
return(NULL);
}
if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug2("Remote version: %u", ret->version);
/* Check for extensions */
while (sshbuf_len(msg) > 0) {
char *name;
u_char *value;
size_t vlen;
int known = 0;
if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
(r = sshbuf_get_string(msg, &value, &vlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp(name, "posix-rename@openssh.com") == 0 &&
strcmp((char *)value, "1") == 0) {
ret->exts |= SFTP_EXT_POSIX_RENAME;
known = 1;
} else if (strcmp(name, "statvfs@openssh.com") == 0 &&
strcmp((char *)value, "2") == 0) {
ret->exts |= SFTP_EXT_STATVFS;
known = 1;
} else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
strcmp((char *)value, "2") == 0) {
ret->exts |= SFTP_EXT_FSTATVFS;
known = 1;
} else if (strcmp(name, "hardlink@openssh.com") == 0 &&
strcmp((char *)value, "1") == 0) {
ret->exts |= SFTP_EXT_HARDLINK;
known = 1;
} else if (strcmp(name, "fsync@openssh.com") == 0 &&
strcmp((char *)value, "1") == 0) {
ret->exts |= SFTP_EXT_FSYNC;
known = 1;
+ } else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
+ strcmp((char *)value, "1") == 0) {
+ ret->exts |= SFTP_EXT_LSETSTAT;
+ known = 1;
}
if (known) {
debug2("Server supports extension \"%s\" revision %s",
name, value);
} else {
debug2("Unrecognised server extension \"%s\"", name);
}
free(name);
free(value);
}
sshbuf_free(msg);
/* Some filexfer v.0 servers don't support large packets */
if (ret->version == 0)
ret->transfer_buflen = MINIMUM(ret->transfer_buflen, 20480);
ret->limit_kbps = limit_kbps;
if (ret->limit_kbps > 0) {
bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
ret->transfer_buflen);
bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
ret->transfer_buflen);
}
return ret;
}
u_int
sftp_proto_version(struct sftp_conn *conn)
{
return conn->version;
}
int
do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
{
u_int id, status;
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't close file: %s", fx2txt(status));
sshbuf_free(msg);
return status == SSH2_FX_OK ? 0 : -1;
}
static int
do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
SFTP_DIRENT ***dir)
{
struct sshbuf *msg;
u_int count, id, i, expected_id, ents = 0;
size_t handle_len;
u_char type, *handle;
int status = SSH2_FX_FAILURE;
int r;
if (dir)
*dir = NULL;
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, path)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
handle = get_handle(conn, id, &handle_len,
"remote readdir(\"%s\")", path);
if (handle == NULL) {
sshbuf_free(msg);
return -1;
}
if (dir) {
ents = 0;
*dir = xcalloc(1, sizeof(**dir));
(*dir)[0] = NULL;
}
for (; !interrupted;) {
id = expected_id = conn->msg_id++;
debug3("Sending SSH2_FXP_READDIR I:%u", id);
sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
sshbuf_reset(msg);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("Received reply T:%u I:%u", type, id);
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int rstatus;
if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
debug3("Received SSH2_FXP_STATUS %d", rstatus);
if (rstatus == SSH2_FX_EOF)
break;
error("Couldn't read directory: %s", fx2txt(rstatus));
goto out;
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);
if ((r = sshbuf_get_u32(msg, &count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (count > SSHBUF_SIZE_MAX)
fatal("%s: nonsensical number of entries", __func__);
if (count == 0)
break;
debug3("Received %d SSH2_FXP_NAME responses", count);
for (i = 0; i < count; i++) {
char *filename, *longname;
Attrib a;
if ((r = sshbuf_get_cstring(msg, &filename,
NULL)) != 0 ||
(r = sshbuf_get_cstring(msg, &longname,
NULL)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if ((r = decode_attrib(msg, &a)) != 0) {
error("%s: couldn't decode attrib: %s",
__func__, ssh_err(r));
free(filename);
free(longname);
sshbuf_free(msg);
return -1;
}
if (print_flag)
mprintf("%s\n", longname);
/*
* Directory entries should never contain '/'
* These can be used to attack recursive ops
* (e.g. send '../../../../etc/passwd')
*/
if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) {
error("Server sent suspect path \"%s\" "
"during readdir of \"%s\"", filename, path);
} else if (dir) {
*dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
(*dir)[ents] = xcalloc(1, sizeof(***dir));
(*dir)[ents]->filename = xstrdup(filename);
(*dir)[ents]->longname = xstrdup(longname);
memcpy(&(*dir)[ents]->a, &a, sizeof(a));
(*dir)[++ents] = NULL;
}
free(filename);
free(longname);
}
}
status = 0;
out:
sshbuf_free(msg);
do_close(conn, handle, handle_len);
free(handle);
if (status != 0 && dir != NULL) {
/* Don't return results on error */
free_sftp_dirents(*dir);
*dir = NULL;
} else if (interrupted && dir != NULL && *dir != NULL) {
/* Don't return partial matches on interrupt */
free_sftp_dirents(*dir);
*dir = xcalloc(1, sizeof(**dir));
**dir = NULL;
}
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
{
return(do_lsreaddir(conn, path, 0, dir));
}
void free_sftp_dirents(SFTP_DIRENT **s)
{
int i;
if (s == NULL)
return;
for (i = 0; s[i]; i++) {
free(s[i]->filename);
free(s[i]->longname);
free(s[i]);
}
free(s);
}
int
do_rm(struct sftp_conn *conn, const char *path)
{
u_int status, id;
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
id = conn->msg_id++;
send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't delete file: %s", fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
{
u_int status, id;
id = conn->msg_id++;
send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
strlen(path), a);
status = get_status(conn, id);
if (status != SSH2_FX_OK && print_flag)
error("Couldn't create directory: %s", fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_rmdir(struct sftp_conn *conn, const char *path)
{
u_int status, id;
id = conn->msg_id++;
send_string_request(conn, id, SSH2_FXP_RMDIR, path,
strlen(path));
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't remove directory: %s", fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
Attrib *
do_stat(struct sftp_conn *conn, const char *path, int quiet)
{
u_int id;
id = conn->msg_id++;
send_string_request(conn, id,
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
path, strlen(path));
return(get_decode_stat(conn, id, quiet));
}
Attrib *
do_lstat(struct sftp_conn *conn, const char *path, int quiet)
{
u_int id;
if (conn->version == 0) {
if (quiet)
debug("Server version does not support lstat operation");
else
logit("Server version does not support lstat operation");
return(do_stat(conn, path, quiet));
}
id = conn->msg_id++;
send_string_request(conn, id, SSH2_FXP_LSTAT, path,
strlen(path));
return(get_decode_stat(conn, id, quiet));
}
#ifdef notyet
Attrib *
do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
int quiet)
{
u_int id;
id = conn->msg_id++;
send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
handle_len);
return(get_decode_stat(conn, id, quiet));
}
#endif
int
do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
{
u_int status, id;
id = conn->msg_id++;
send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
strlen(path), a);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't setstat on \"%s\": %s", path,
fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
Attrib *a)
{
u_int status, id;
id = conn->msg_id++;
send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
handle_len, a);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't fsetstat: %s", fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
char *
do_realpath(struct sftp_conn *conn, const char *path)
{
struct sshbuf *msg;
u_int expected_id, count, id;
char *filename, *longname;
Attrib a;
u_char type;
int r;
expected_id = id = conn->msg_id++;
send_string_request(conn, id, SSH2_FXP_REALPATH, path,
strlen(path));
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
error("Couldn't canonicalize: %s", fx2txt(status));
sshbuf_free(msg);
return NULL;
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);
if ((r = sshbuf_get_u32(msg, &count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (count != 1)
fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
(r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
(r = decode_attrib(msg, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename,
(unsigned long)a.size);
free(longname);
sshbuf_free(msg);
return(filename);
}
int
do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
int force_legacy)
{
struct sshbuf *msg;
u_int status, id;
int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Send rename request */
id = conn->msg_id++;
if (use_ext) {
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg,
"posix-rename@openssh.com")) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else {
if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
(r = sshbuf_put_cstring(msg, newpath)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message %s \"%s\" -> \"%s\"",
use_ext ? "posix-rename@openssh.com" :
"SSH2_FXP_RENAME", oldpath, newpath);
sshbuf_free(msg);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
{
struct sshbuf *msg;
u_int status, id;
int r;
if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
error("Server does not support hardlink@openssh.com extension");
return -1;
}
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Send link request */
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
(r = sshbuf_put_cstring(msg, newpath)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
oldpath, newpath);
sshbuf_free(msg);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
{
struct sshbuf *msg;
u_int status, id;
int r;
if (conn->version < 3) {
error("This server does not support the symlink operation");
return(SSH2_FX_OP_UNSUPPORTED);
}
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Send symlink request */
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
(r = sshbuf_put_cstring(msg, newpath)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
newpath);
sshbuf_free(msg);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
newpath, fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
int
do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
{
struct sshbuf *msg;
u_int status, id;
int r;
/* Silently return if the extension is not supported */
if ((conn->exts & SFTP_EXT_FSYNC) == 0)
return -1;
/* Send fsync request */
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message fsync@openssh.com I:%u", id);
sshbuf_free(msg);
status = get_status(conn, id);
if (status != SSH2_FX_OK)
error("Couldn't sync file: %s", fx2txt(status));
return status == SSH2_FX_OK ? 0 : -1;
}
#ifdef notyet
char *
do_readlink(struct sftp_conn *conn, const char *path)
{
struct sshbuf *msg;
u_int expected_id, count, id;
char *filename, *longname;
Attrib a;
u_char type;
int r;
expected_id = id = conn->msg_id++;
send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
error("Couldn't readlink: %s", fx2txt(status));
sshbuf_free(msg);
return(NULL);
} else if (type != SSH2_FXP_NAME)
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
SSH2_FXP_NAME, type);
if ((r = sshbuf_get_u32(msg, &count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (count != 1)
fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
(r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
(r = decode_attrib(msg, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("SSH_FXP_READLINK %s -> %s", path, filename);
free(longname);
sshbuf_free(msg);
return filename;
}
#endif
int
do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
int quiet)
{
struct sshbuf *msg;
u_int id;
int r;
if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
error("Server does not support statvfs@openssh.com extension");
return -1;
}
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, path)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
sshbuf_free(msg);
return get_decode_statvfs(conn, st, id, quiet);
}
#ifdef notyet
int
do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
struct sftp_statvfs *st, int quiet)
{
struct sshbuf *msg;
u_int id;
if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
error("Server does not support fstatvfs@openssh.com extension");
return -1;
}
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
sshbuf_free(msg);
return get_decode_statvfs(conn, st, id, quiet);
}
#endif
+int
+do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
+{
+ struct sshbuf *msg;
+ u_int status, id;
+ int r;
+
+ if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
+ error("Server does not support lsetstat@openssh.com extension");
+ return -1;
+ }
+
+ id = conn->msg_id++;
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(msg, path)) != 0 ||
+ (r = encode_attrib(msg, a)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(conn, msg);
+ sshbuf_free(msg);
+
+ status = get_status(conn, id);
+ if (status != SSH2_FX_OK)
+ error("Couldn't setstat on \"%s\": %s", path,
+ fx2txt(status));
+
+ return status == SSH2_FX_OK ? 0 : -1;
+}
+
static void
send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
u_int len, const u_char *handle, u_int handle_len)
{
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
(r = sshbuf_put_u64(msg, offset)) != 0 ||
(r = sshbuf_put_u32(msg, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
sshbuf_free(msg);
}
int
do_download(struct sftp_conn *conn, const char *remote_path,
const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
int fsync_flag)
{
Attrib junk;
struct sshbuf *msg;
u_char *handle;
int local_fd = -1, write_error;
int read_error, write_errno, reordered = 0, r;
u_int64_t offset = 0, size, highwater;
u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
off_t progress_counter;
size_t handle_len;
struct stat st;
struct request {
u_int id;
size_t len;
u_int64_t offset;
TAILQ_ENTRY(request) tq;
};
TAILQ_HEAD(reqhead, request) requests;
struct request *req;
u_char type;
TAILQ_INIT(&requests);
if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
return -1;
/* Do not preserve set[ug]id here, as we do not preserve ownership */
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
mode = a->perm & 0777;
else
mode = 0666;
if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
(!S_ISREG(a->perm))) {
error("Cannot download non-regular file: %s", remote_path);
return(-1);
}
if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
size = a->size;
else
size = 0;
buflen = conn->transfer_buflen;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
attrib_clear(&junk); /* Send empty attributes */
/* Send open request */
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
(r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
(r = encode_attrib(msg, &junk)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
handle = get_handle(conn, id, &handle_len,
"remote open(\"%s\")", remote_path);
if (handle == NULL) {
sshbuf_free(msg);
return(-1);
}
local_fd = open(local_path,
O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
if (local_fd == -1) {
error("Couldn't open local file \"%s\" for writing: %s",
local_path, strerror(errno));
goto fail;
}
offset = highwater = 0;
if (resume_flag) {
if (fstat(local_fd, &st) == -1) {
error("Unable to stat local file \"%s\": %s",
local_path, strerror(errno));
goto fail;
}
if (st.st_size < 0) {
error("\"%s\" has negative size", local_path);
goto fail;
}
if ((u_int64_t)st.st_size > size) {
error("Unable to resume download of \"%s\": "
"local file is larger than remote", local_path);
fail:
do_close(conn, handle, handle_len);
sshbuf_free(msg);
free(handle);
if (local_fd != -1)
close(local_fd);
return -1;
}
offset = highwater = st.st_size;
}
/* Read from remote and write to local */
write_error = read_error = write_errno = num_req = 0;
max_req = 1;
progress_counter = offset;
if (showprogress && size != 0)
start_progress_meter(remote_path, size, &progress_counter);
while (num_req > 0 || max_req > 0) {
u_char *data;
size_t len;
/*
* Simulate EOF on interrupt: stop sending new requests and
* allow outstanding requests to drain gracefully
*/
if (interrupted) {
if (num_req == 0) /* If we haven't started yet... */
break;
max_req = 0;
}
/* Send some more requests */
while (num_req < max_req) {
debug3("Request range %llu -> %llu (%d/%d)",
(unsigned long long)offset,
(unsigned long long)offset + buflen - 1,
num_req, max_req);
req = xcalloc(1, sizeof(*req));
req->id = conn->msg_id++;
req->len = buflen;
req->offset = offset;
offset += buflen;
num_req++;
TAILQ_INSERT_TAIL(&requests, req, tq);
send_read_request(conn, req->id, req->offset,
req->len, handle, handle_len);
}
sshbuf_reset(msg);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
/* Find the request in our queue */
for (req = TAILQ_FIRST(&requests);
req != NULL && req->id != id;
req = TAILQ_NEXT(req, tq))
;
if (req == NULL)
fatal("Unexpected reply %u", id);
switch (type) {
case SSH2_FXP_STATUS:
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if (status != SSH2_FX_EOF)
read_error = 1;
max_req = 0;
TAILQ_REMOVE(&requests, req, tq);
free(req);
num_req--;
break;
case SSH2_FXP_DATA:
if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
debug3("Received data %llu -> %llu",
(unsigned long long)req->offset,
(unsigned long long)req->offset + len - 1);
if (len > req->len)
fatal("Received more data than asked for "
"%zu > %zu", len, req->len);
if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
atomicio(vwrite, local_fd, data, len) != len) &&
!write_error) {
write_errno = errno;
write_error = 1;
max_req = 0;
}
else if (!reordered && req->offset <= highwater)
highwater = req->offset + len;
else if (!reordered && req->offset > highwater)
reordered = 1;
progress_counter += len;
free(data);
if (len == req->len) {
TAILQ_REMOVE(&requests, req, tq);
free(req);
num_req--;
} else {
/* Resend the request for the missing data */
debug3("Short data block, re-requesting "
"%llu -> %llu (%2d)",
(unsigned long long)req->offset + len,
(unsigned long long)req->offset +
req->len - 1, num_req);
req->id = conn->msg_id++;
req->len -= len;
req->offset += len;
send_read_request(conn, req->id,
req->offset, req->len, handle, handle_len);
/* Reduce the request size */
if (len < buflen)
buflen = MAXIMUM(MIN_READ_SIZE, len);
}
if (max_req > 0) { /* max_req = 0 iff EOF received */
if (size > 0 && offset > size) {
/* Only one request at a time
* after the expected EOF */
debug3("Finish at %llu (%2d)",
(unsigned long long)offset,
num_req);
max_req = 1;
} else if (max_req <= conn->num_requests) {
++max_req;
}
}
break;
default:
fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
SSH2_FXP_DATA, type);
}
}
if (showprogress && size)
stop_progress_meter();
/* Sanity check */
if (TAILQ_FIRST(&requests) != NULL)
fatal("Transfer complete, but requests still in queue");
/* Truncate at highest contiguous point to avoid holes on interrupt */
if (read_error || write_error || interrupted) {
if (reordered && resume_flag) {
error("Unable to resume download of \"%s\": "
"server reordered requests", local_path);
}
debug("truncating at %llu", (unsigned long long)highwater);
if (ftruncate(local_fd, highwater) == -1)
error("ftruncate \"%s\": %s", local_path,
strerror(errno));
}
if (read_error) {
error("Couldn't read from remote file \"%s\" : %s",
remote_path, fx2txt(status));
status = -1;
do_close(conn, handle, handle_len);
} else if (write_error) {
error("Couldn't write to \"%s\": %s", local_path,
strerror(write_errno));
status = SSH2_FX_FAILURE;
do_close(conn, handle, handle_len);
} else {
if (do_close(conn, handle, handle_len) != 0 || interrupted)
status = SSH2_FX_FAILURE;
else
status = SSH2_FX_OK;
/* Override umask and utimes if asked */
#ifdef HAVE_FCHMOD
if (preserve_flag && fchmod(local_fd, mode) == -1)
#else
if (preserve_flag && chmod(local_path, mode) == -1)
#endif /* HAVE_FCHMOD */
error("Couldn't set mode on \"%s\": %s", local_path,
strerror(errno));
if (preserve_flag &&
(a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
struct timeval tv[2];
tv[0].tv_sec = a->atime;
tv[1].tv_sec = a->mtime;
tv[0].tv_usec = tv[1].tv_usec = 0;
if (utimes(local_path, tv) == -1)
error("Can't set times on \"%s\": %s",
local_path, strerror(errno));
}
if (fsync_flag) {
debug("syncing \"%s\"", local_path);
if (fsync(local_fd) == -1)
error("Couldn't sync file \"%s\": %s",
local_path, strerror(errno));
}
}
close(local_fd);
sshbuf_free(msg);
free(handle);
return status == SSH2_FX_OK ? 0 : -1;
}
static int
download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
int resume_flag, int fsync_flag)
{
int i, ret = 0;
SFTP_DIRENT **dir_entries;
char *filename, *new_src = NULL, *new_dst = NULL;
mode_t mode = 0777;
if (depth >= MAX_DIR_DEPTH) {
error("Maximum directory depth exceeded: %d levels", depth);
return -1;
}
if (dirattrib == NULL &&
(dirattrib = do_stat(conn, src, 1)) == NULL) {
error("Unable to stat remote directory \"%s\"", src);
return -1;
}
if (!S_ISDIR(dirattrib->perm)) {
error("\"%s\" is not a directory", src);
return -1;
}
if (print_flag)
mprintf("Retrieving %s\n", src);
if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
mode = dirattrib->perm & 01777;
else {
debug("Server did not send permissions for "
"directory \"%s\"", dst);
}
if (mkdir(dst, mode) == -1 && errno != EEXIST) {
error("mkdir %s: %s", dst, strerror(errno));
return -1;
}
if (do_readdir(conn, src, &dir_entries) == -1) {
error("%s: Failed to get directory contents", src);
return -1;
}
for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
free(new_dst);
free(new_src);
filename = dir_entries[i]->filename;
new_dst = path_append(dst, filename);
new_src = path_append(src, filename);
if (S_ISDIR(dir_entries[i]->a.perm)) {
if (strcmp(filename, ".") == 0 ||
strcmp(filename, "..") == 0)
continue;
if (download_dir_internal(conn, new_src, new_dst,
depth + 1, &(dir_entries[i]->a), preserve_flag,
print_flag, resume_flag, fsync_flag) == -1)
ret = -1;
} else if (S_ISREG(dir_entries[i]->a.perm) ) {
if (do_download(conn, new_src, new_dst,
&(dir_entries[i]->a), preserve_flag,
resume_flag, fsync_flag) == -1) {
error("Download of file %s to %s failed",
new_src, new_dst);
ret = -1;
}
} else
logit("%s: not a regular file\n", new_src);
}
free(new_dst);
free(new_src);
if (preserve_flag) {
if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
struct timeval tv[2];
tv[0].tv_sec = dirattrib->atime;
tv[1].tv_sec = dirattrib->mtime;
tv[0].tv_usec = tv[1].tv_usec = 0;
if (utimes(dst, tv) == -1)
error("Can't set times on \"%s\": %s",
dst, strerror(errno));
} else
debug("Server did not send times for directory "
"\"%s\"", dst);
}
free_sftp_dirents(dir_entries);
return ret;
}
int
download_dir(struct sftp_conn *conn, const char *src, const char *dst,
Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
int fsync_flag)
{
char *src_canon;
int ret;
if ((src_canon = do_realpath(conn, src)) == NULL) {
error("Unable to canonicalize path \"%s\"", src);
return -1;
}
ret = download_dir_internal(conn, src_canon, dst, 0,
dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
free(src_canon);
return ret;
}
int
do_upload(struct sftp_conn *conn, const char *local_path,
const char *remote_path, int preserve_flag, int resume, int fsync_flag)
{
int r, local_fd;
u_int status = SSH2_FX_OK;
u_int id;
u_char type;
off_t offset, progress_counter;
u_char *handle, *data;
struct sshbuf *msg;
struct stat sb;
Attrib a, *c = NULL;
u_int32_t startid;
u_int32_t ackid;
struct outstanding_ack {
u_int id;
u_int len;
off_t offset;
TAILQ_ENTRY(outstanding_ack) tq;
};
TAILQ_HEAD(ackhead, outstanding_ack) acks;
struct outstanding_ack *ack = NULL;
size_t handle_len;
TAILQ_INIT(&acks);
if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
error("Couldn't open local file \"%s\" for reading: %s",
local_path, strerror(errno));
return(-1);
}
if (fstat(local_fd, &sb) == -1) {
error("Couldn't fstat local file \"%s\": %s",
local_path, strerror(errno));
close(local_fd);
return(-1);
}
if (!S_ISREG(sb.st_mode)) {
error("%s is not a regular file", local_path);
close(local_fd);
return(-1);
}
stat_to_attrib(&sb, &a);
a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
a.perm &= 0777;
if (!preserve_flag)
a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
if (resume) {
/* Get remote file size if it exists */
if ((c = do_stat(conn, remote_path, 0)) == NULL) {
close(local_fd);
return -1;
}
if ((off_t)c->size >= sb.st_size) {
error("destination file bigger or same size as "
"source file");
close(local_fd);
return -1;
}
if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
close(local_fd);
return -1;
}
}
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* Send open request */
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
(r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
(resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
(r = encode_attrib(msg, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
sshbuf_reset(msg);
handle = get_handle(conn, id, &handle_len,
"remote open(\"%s\")", remote_path);
if (handle == NULL) {
close(local_fd);
sshbuf_free(msg);
return -1;
}
startid = ackid = id + 1;
data = xmalloc(conn->transfer_buflen);
/* Read from local and write to remote */
offset = progress_counter = (resume ? c->size : 0);
if (showprogress)
start_progress_meter(local_path, sb.st_size,
&progress_counter);
for (;;) {
int len;
/*
* Can't use atomicio here because it returns 0 on EOF,
* thus losing the last block of the file.
* Simulate an EOF on interrupt, allowing ACKs from the
* server to drain.
*/
if (interrupted || status != SSH2_FX_OK)
len = 0;
else do
len = read(local_fd, data, conn->transfer_buflen);
while ((len == -1) &&
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
if (len == -1)
fatal("Couldn't read from \"%s\": %s", local_path,
strerror(errno));
if (len != 0) {
ack = xcalloc(1, sizeof(*ack));
ack->id = ++id;
ack->offset = offset;
ack->len = len;
TAILQ_INSERT_TAIL(&acks, ack, tq);
sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
(r = sshbuf_put_u32(msg, ack->id)) != 0 ||
(r = sshbuf_put_string(msg, handle,
handle_len)) != 0 ||
(r = sshbuf_put_u64(msg, offset)) != 0 ||
(r = sshbuf_put_string(msg, data, len)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
id, (unsigned long long)offset, len);
} else if (TAILQ_FIRST(&acks) == NULL)
break;
if (ack == NULL)
fatal("Unexpected ACK %u", id);
if (id == startid || len == 0 ||
id - ackid >= conn->num_requests) {
u_int rid;
sshbuf_reset(msg);
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &rid)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if (type != SSH2_FXP_STATUS)
fatal("Expected SSH2_FXP_STATUS(%d) packet, "
"got %d", SSH2_FXP_STATUS, type);
if ((r = sshbuf_get_u32(msg, &status)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
debug3("SSH2_FXP_STATUS %u", status);
/* Find the request in our queue */
for (ack = TAILQ_FIRST(&acks);
ack != NULL && ack->id != rid;
ack = TAILQ_NEXT(ack, tq))
;
if (ack == NULL)
fatal("Can't find request for ID %u", rid);
TAILQ_REMOVE(&acks, ack, tq);
debug3("In write loop, ack for %u %u bytes at %lld",
ack->id, ack->len, (long long)ack->offset);
++ackid;
progress_counter += ack->len;
free(ack);
}
offset += len;
if (offset < 0)
fatal("%s: offset < 0", __func__);
}
sshbuf_free(msg);
if (showprogress)
stop_progress_meter();
free(data);
if (status != SSH2_FX_OK) {
error("Couldn't write to remote file \"%s\": %s",
remote_path, fx2txt(status));
status = SSH2_FX_FAILURE;
}
if (close(local_fd) == -1) {
error("Couldn't close local file \"%s\": %s", local_path,
strerror(errno));
status = SSH2_FX_FAILURE;
}
/* Override umask and utimes if asked */
if (preserve_flag)
do_fsetstat(conn, handle, handle_len, &a);
if (fsync_flag)
(void)do_fsync(conn, handle, handle_len);
if (do_close(conn, handle, handle_len) != 0)
status = SSH2_FX_FAILURE;
free(handle);
return status == SSH2_FX_OK ? 0 : -1;
}
static int
upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
{
int ret = 0;
DIR *dirp;
struct dirent *dp;
char *filename, *new_src = NULL, *new_dst = NULL;
struct stat sb;
Attrib a, *dirattrib;
if (depth >= MAX_DIR_DEPTH) {
error("Maximum directory depth exceeded: %d levels", depth);
return -1;
}
if (stat(src, &sb) == -1) {
error("Couldn't stat directory \"%s\": %s",
src, strerror(errno));
return -1;
}
if (!S_ISDIR(sb.st_mode)) {
error("\"%s\" is not a directory", src);
return -1;
}
if (print_flag)
mprintf("Entering %s\n", src);
attrib_clear(&a);
stat_to_attrib(&sb, &a);
a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
a.perm &= 01777;
if (!preserve_flag)
a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
/*
* sftp lacks a portable status value to match errno EEXIST,
* so if we get a failure back then we must check whether
* the path already existed and is a directory.
*/
if (do_mkdir(conn, dst, &a, 0) != 0) {
if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
return -1;
if (!S_ISDIR(dirattrib->perm)) {
error("\"%s\" exists but is not a directory", dst);
return -1;
}
}
if ((dirp = opendir(src)) == NULL) {
error("Failed to open dir \"%s\": %s", src, strerror(errno));
return -1;
}
while (((dp = readdir(dirp)) != NULL) && !interrupted) {
if (dp->d_ino == 0)
continue;
free(new_dst);
free(new_src);
filename = dp->d_name;
new_dst = path_append(dst, filename);
new_src = path_append(src, filename);
if (lstat(new_src, &sb) == -1) {
logit("%s: lstat failed: %s", filename,
strerror(errno));
ret = -1;
} else if (S_ISDIR(sb.st_mode)) {
if (strcmp(filename, ".") == 0 ||
strcmp(filename, "..") == 0)
continue;
if (upload_dir_internal(conn, new_src, new_dst,
depth + 1, preserve_flag, print_flag, resume,
fsync_flag) == -1)
ret = -1;
} else if (S_ISREG(sb.st_mode)) {
if (do_upload(conn, new_src, new_dst,
preserve_flag, resume, fsync_flag) == -1) {
error("Uploading of file %s to %s failed!",
new_src, new_dst);
ret = -1;
}
} else
logit("%s: not a regular file\n", filename);
}
free(new_dst);
free(new_src);
do_setstat(conn, dst, &a);
(void) closedir(dirp);
return ret;
}
int
upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
int preserve_flag, int print_flag, int resume, int fsync_flag)
{
char *dst_canon;
int ret;
if ((dst_canon = do_realpath(conn, dst)) == NULL) {
error("Unable to canonicalize path \"%s\"", dst);
return -1;
}
ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
print_flag, resume, fsync_flag);
free(dst_canon);
return ret;
}
char *
path_append(const char *p1, const char *p2)
{
char *ret;
size_t len = strlen(p1) + strlen(p2) + 2;
ret = xmalloc(len);
strlcpy(ret, p1, len);
if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
strlcat(ret, "/", len);
strlcat(ret, p2, len);
return(ret);
}
diff --git a/sftp-client.h b/sftp-client.h
index 14a3b8182c49..63a9b8b13bdc 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -1,142 +1,145 @@
-/* $OpenBSD: sftp-client.h,v 1.27 2015/05/08 06:45:13 djm Exp $ */
+/* $OpenBSD: sftp-client.h,v 1.28 2019/01/16 23:23:45 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Client side of SSH2 filexfer protocol */
#ifndef _SFTP_CLIENT_H
#define _SFTP_CLIENT_H
#ifdef USE_SYSTEM_GLOB
# include <glob.h>
#else
# include "openbsd-compat/glob.h"
#endif
typedef struct SFTP_DIRENT SFTP_DIRENT;
struct SFTP_DIRENT {
char *filename;
char *longname;
Attrib a;
};
/*
* Used for statvfs responses on the wire from the server, because the
* server's native format may be larger than the client's.
*/
struct sftp_statvfs {
u_int64_t f_bsize;
u_int64_t f_frsize;
u_int64_t f_blocks;
u_int64_t f_bfree;
u_int64_t f_bavail;
u_int64_t f_files;
u_int64_t f_ffree;
u_int64_t f_favail;
u_int64_t f_fsid;
u_int64_t f_flag;
u_int64_t f_namemax;
};
/*
* Initialise a SSH filexfer connection. Returns NULL on error or
* a pointer to a initialized sftp_conn struct on success.
*/
struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t);
u_int sftp_proto_version(struct sftp_conn *);
/* Close file referred to by 'handle' */
int do_close(struct sftp_conn *, const u_char *, u_int);
/* Read contents of 'path' to NULL-terminated array 'dir' */
int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***);
/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */
void free_sftp_dirents(SFTP_DIRENT **);
/* Delete file 'path' */
int do_rm(struct sftp_conn *, const char *);
/* Create directory 'path' */
int do_mkdir(struct sftp_conn *, const char *, Attrib *, int);
/* Remove directory 'path' */
int do_rmdir(struct sftp_conn *, const char *);
/* Get file attributes of 'path' (follows symlinks) */
Attrib *do_stat(struct sftp_conn *, const char *, int);
/* Get file attributes of 'path' (does not follow symlinks) */
Attrib *do_lstat(struct sftp_conn *, const char *, int);
/* Set file attributes of 'path' */
int do_setstat(struct sftp_conn *, const char *, Attrib *);
/* Set file attributes of open file 'handle' */
int do_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *);
+/* Set file attributes of 'path', not following symlinks */
+int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
+
/* Canonicalise 'path' - caller must free result */
char *do_realpath(struct sftp_conn *, const char *);
/* Get statistics for filesystem hosting file at "path" */
int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
/* Rename 'oldpath' to 'newpath' */
int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy);
/* Link 'oldpath' to 'newpath' */
int do_hardlink(struct sftp_conn *, const char *, const char *);
/* Rename 'oldpath' to 'newpath' */
int do_symlink(struct sftp_conn *, const char *, const char *);
/* Call fsync() on open file 'handle' */
int do_fsync(struct sftp_conn *conn, u_char *, u_int);
/*
* Download 'remote_path' to 'local_path'. Preserve permissions and times
* if 'pflag' is set
*/
int do_download(struct sftp_conn *, const char *, const char *,
Attrib *, int, int, int);
/*
* Recursively download 'remote_directory' to 'local_directory'. Preserve
* times if 'pflag' is set
*/
int download_dir(struct sftp_conn *, const char *, const char *,
Attrib *, int, int, int, int);
/*
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
* if 'pflag' is set
*/
int do_upload(struct sftp_conn *, const char *, const char *, int, int, int);
/*
* Recursively upload 'local_directory' to 'remote_directory'. Preserve
* times if 'pflag' is set
*/
int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
int);
/* Concatenate paths, taking care of slashes. Caller must free result. */
char *path_append(const char *, const char *);
#endif
diff --git a/sftp-common.c b/sftp-common.c
index 5d743d3b2b12..677f27d63c53 100644
--- a/sftp-common.c
+++ b/sftp-common.c
@@ -1,258 +1,259 @@
/* $OpenBSD: sftp-common.c,v 1.31 2018/09/13 15:23:32 millert Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
+#include <unistd.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
#include "xmalloc.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "sftp.h"
#include "sftp-common.h"
/* Clear contents of attributes structure */
void
attrib_clear(Attrib *a)
{
a->flags = 0;
a->size = 0;
a->uid = 0;
a->gid = 0;
a->perm = 0;
a->atime = 0;
a->mtime = 0;
}
/* Convert from struct stat to filexfer attribs */
void
stat_to_attrib(const struct stat *st, Attrib *a)
{
attrib_clear(a);
a->flags = 0;
a->flags |= SSH2_FILEXFER_ATTR_SIZE;
a->size = st->st_size;
a->flags |= SSH2_FILEXFER_ATTR_UIDGID;
a->uid = st->st_uid;
a->gid = st->st_gid;
a->flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
a->perm = st->st_mode;
a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
a->atime = st->st_atime;
a->mtime = st->st_mtime;
}
/* Convert from filexfer attribs to struct stat */
void
attrib_to_stat(const Attrib *a, struct stat *st)
{
memset(st, 0, sizeof(*st));
if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
st->st_size = a->size;
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
st->st_uid = a->uid;
st->st_gid = a->gid;
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
st->st_mode = a->perm;
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
st->st_atime = a->atime;
st->st_mtime = a->mtime;
}
}
/* Decode attributes in buffer */
int
decode_attrib(struct sshbuf *b, Attrib *a)
{
int r;
attrib_clear(a);
if ((r = sshbuf_get_u32(b, &a->flags)) != 0)
return r;
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
if ((r = sshbuf_get_u64(b, &a->size)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
if ((r = sshbuf_get_u32(b, &a->uid)) != 0 ||
(r = sshbuf_get_u32(b, &a->gid)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
if ((r = sshbuf_get_u32(b, &a->perm)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
if ((r = sshbuf_get_u32(b, &a->atime)) != 0 ||
(r = sshbuf_get_u32(b, &a->mtime)) != 0)
return r;
}
/* vendor-specific extensions */
if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) {
char *type;
u_char *data;
size_t dlen;
u_int i, count;
if ((r = sshbuf_get_u32(b, &count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; i < count; i++) {
if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
(r = sshbuf_get_string(b, &data, &dlen)) != 0)
return r;
debug3("Got file attribute \"%.100s\" len %zu",
type, dlen);
free(type);
free(data);
}
}
return 0;
}
/* Encode attributes to buffer */
int
encode_attrib(struct sshbuf *b, const Attrib *a)
{
int r;
if ((r = sshbuf_put_u32(b, a->flags)) != 0)
return r;
if (a->flags & SSH2_FILEXFER_ATTR_SIZE) {
if ((r = sshbuf_put_u64(b, a->size)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_UIDGID) {
if ((r = sshbuf_put_u32(b, a->uid)) != 0 ||
(r = sshbuf_put_u32(b, a->gid)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
if ((r = sshbuf_put_u32(b, a->perm)) != 0)
return r;
}
if (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
if ((r = sshbuf_put_u32(b, a->atime)) != 0 ||
(r = sshbuf_put_u32(b, a->mtime)) != 0)
return r;
}
return 0;
}
/* Convert from SSH2_FX_ status to text error message */
const char *
fx2txt(int status)
{
switch (status) {
case SSH2_FX_OK:
return("No error");
case SSH2_FX_EOF:
return("End of file");
case SSH2_FX_NO_SUCH_FILE:
return("No such file or directory");
case SSH2_FX_PERMISSION_DENIED:
return("Permission denied");
case SSH2_FX_FAILURE:
return("Failure");
case SSH2_FX_BAD_MESSAGE:
return("Bad message");
case SSH2_FX_NO_CONNECTION:
return("No connection");
case SSH2_FX_CONNECTION_LOST:
return("Connection lost");
case SSH2_FX_OP_UNSUPPORTED:
return("Operation unsupported");
default:
return("Unknown status");
}
/* NOTREACHED */
}
/*
* drwxr-xr-x 5 markus markus 1024 Jan 13 18:39 .ssh
*/
char *
ls_file(const char *name, const struct stat *st, int remote, int si_units)
{
int ulen, glen, sz = 0;
struct tm *ltime = localtime(&st->st_mtime);
const char *user, *group;
char buf[1024], lc[8], mode[11+1], tbuf[12+1], ubuf[11+1], gbuf[11+1];
char sbuf[FMT_SCALED_STRSIZE];
time_t now;
strmode(st->st_mode, mode);
if (remote) {
snprintf(ubuf, sizeof ubuf, "%u", (u_int)st->st_uid);
user = ubuf;
snprintf(gbuf, sizeof gbuf, "%u", (u_int)st->st_gid);
group = gbuf;
strlcpy(lc, "?", sizeof(lc));
} else {
user = user_from_uid(st->st_uid, 0);
group = group_from_gid(st->st_gid, 0);
snprintf(lc, sizeof(lc), "%u", (u_int)st->st_nlink);
}
if (ltime != NULL) {
now = time(NULL);
if (now - (365*24*60*60)/2 < st->st_mtime &&
now >= st->st_mtime)
sz = strftime(tbuf, sizeof tbuf, "%b %e %H:%M", ltime);
else
sz = strftime(tbuf, sizeof tbuf, "%b %e %Y", ltime);
}
if (sz == 0)
tbuf[0] = '\0';
ulen = MAXIMUM(strlen(user), 8);
glen = MAXIMUM(strlen(group), 8);
if (si_units) {
fmt_scaled((long long)st->st_size, sbuf);
snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8s %s %s",
mode, lc, ulen, user, glen, group,
sbuf, tbuf, name);
} else {
snprintf(buf, sizeof buf, "%s %3s %-*s %-*s %8llu %s %s",
mode, lc, ulen, user, glen, group,
(unsigned long long)st->st_size, tbuf, name);
}
return xstrdup(buf);
}
diff --git a/sftp-server-main.c b/sftp-server-main.c
index c6ccd623eab9..6230d897d747 100644
--- a/sftp-server-main.c
+++ b/sftp-server-main.c
@@ -1,53 +1,55 @@
/* $OpenBSD: sftp-server-main.c,v 1.5 2016/02/15 09:47:49 dtucker Exp $ */
/*
* Copyright (c) 2008 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include "log.h"
#include "sftp.h"
#include "misc.h"
#include "xmalloc.h"
void
cleanup_exit(int i)
{
sftp_server_cleanup_exit(i);
}
int
main(int argc, char **argv)
{
struct passwd *user_pw;
ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ seed_rng();
+
if ((user_pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found for uid %lu\n",
(u_long)getuid());
return 1;
}
return (sftp_server_main(argc, argv, user_pw));
}
diff --git a/sftp-server.0 b/sftp-server.0
index 4c42b26c95d8..fb84373d9a4f 100644
--- a/sftp-server.0
+++ b/sftp-server.0
@@ -1,96 +1,96 @@
SFTP-SERVER(8) System Manager's Manual SFTP-SERVER(8)
NAME
sftp-server M-bM-^@M-^S SFTP server subsystem
SYNOPSIS
sftp-server [-ehR] [-d start_directory] [-f log_facility] [-l log_level]
[-P blacklisted_requests] [-p whitelisted_requests]
[-u umask]
sftp-server -Q protocol_feature
DESCRIPTION
sftp-server is a program that speaks the server side of SFTP protocol to
stdout and expects client requests from stdin. sftp-server is not
intended to be called directly, but from sshd(8) using the Subsystem
option.
Command-line flags to sftp-server should be specified in the Subsystem
declaration. See sshd_config(5) for more information.
Valid options are:
-d start_directory
specifies an alternate starting directory for users. The
pathname may contain the following tokens that are expanded at
runtime: %% is replaced by a literal '%', %d is replaced by the
home directory of the user being authenticated, and %u is
replaced by the username of that user. The default is to use the
user's home directory. This option is useful in conjunction with
the sshd_config(5) ChrootDirectory option.
-e Causes sftp-server to print logging information to stderr instead
of syslog for debugging.
-f log_facility
Specifies the facility code that is used when logging messages
from sftp-server. The possible values are: DAEMON, USER, AUTH,
LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
-h Displays sftp-server usage information.
-l log_level
Specifies which messages will be logged by sftp-server. The
possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG,
DEBUG1, DEBUG2, and DEBUG3. INFO and VERBOSE log transactions
that sftp-server performs on behalf of the client. DEBUG and
DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher
levels of debugging output. The default is ERROR.
-P blacklisted_requests
Specify a comma-separated list of SFTP protocol requests that are
banned by the server. sftp-server will reply to any blacklisted
request with a failure. The -Q flag can be used to determine the
supported request types. If both a blacklist and a whitelist are
specified, then the blacklist is applied before the whitelist.
-p whitelisted_requests
Specify a comma-separated list of SFTP protocol requests that are
permitted by the server. All request types that are not on the
whitelist will be logged and replied to with a failure message.
Care must be taken when using this feature to ensure that
requests made implicitly by SFTP clients are permitted.
-Q protocol_feature
Query protocol features supported by sftp-server. At present the
only feature that may be queried is M-bM-^@M-^\requestsM-bM-^@M-^], which may be used
for black or whitelisting (flags -P and -p respectively).
-R Places this instance of sftp-server into a read-only mode.
Attempts to open files for writing, as well as other operations
that change the state of the filesystem, will be denied.
-u umask
Sets an explicit umask(2) to be applied to newly-created files
and directories, instead of the user's default mask.
On some systems, sftp-server must be able to access /dev/log for logging
to work, and use of sftp-server in a chroot configuration therefore
requires that syslogd(8) establish a logging socket inside the chroot
directory.
SEE ALSO
sftp(1), ssh(1), sshd_config(5), sshd(8)
T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh-
filexfer-02.txt, October 2001, work in progress material.
HISTORY
sftp-server first appeared in OpenBSD 2.8.
AUTHORS
Markus Friedl <markus@openbsd.org>
-OpenBSD 6.4 December 11, 2014 OpenBSD 6.4
+OpenBSD 6.5 December 11, 2014 OpenBSD 6.5
diff --git a/sftp-server.c b/sftp-server.c
index ab1b063f2136..19a132bd91ce 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1,1710 +1,1775 @@
-/* $OpenBSD: sftp-server.c,v 1.112 2018/06/01 03:33:53 djm Exp $ */
+/* $OpenBSD: sftp-server.c,v 1.114 2019/01/16 23:22:10 djm Exp $ */
/*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdarg.h>
#include "xmalloc.h"
#include "sshbuf.h"
#include "ssherr.h"
#include "log.h"
#include "misc.h"
#include "match.h"
#include "uidswap.h"
#include "sftp.h"
#include "sftp-common.h"
/* Our verbosity */
static LogLevel log_level = SYSLOG_LEVEL_ERROR;
/* Our client */
static struct passwd *pw = NULL;
static char *client_addr = NULL;
/* input and output queue */
struct sshbuf *iqueue;
struct sshbuf *oqueue;
/* Version of client */
static u_int version;
/* SSH2_FXP_INIT received */
static int init_done;
/* Disable writes */
static int readonly;
/* Requests that are allowed/denied */
static char *request_whitelist, *request_blacklist;
/* portable attributes, etc. */
typedef struct Stat Stat;
struct Stat {
char *name;
char *long_name;
Attrib attrib;
};
/* Packet handlers */
static void process_open(u_int32_t id);
static void process_close(u_int32_t id);
static void process_read(u_int32_t id);
static void process_write(u_int32_t id);
static void process_stat(u_int32_t id);
static void process_lstat(u_int32_t id);
static void process_fstat(u_int32_t id);
static void process_setstat(u_int32_t id);
static void process_fsetstat(u_int32_t id);
static void process_opendir(u_int32_t id);
static void process_readdir(u_int32_t id);
static void process_remove(u_int32_t id);
static void process_mkdir(u_int32_t id);
static void process_rmdir(u_int32_t id);
static void process_realpath(u_int32_t id);
static void process_rename(u_int32_t id);
static void process_readlink(u_int32_t id);
static void process_symlink(u_int32_t id);
static void process_extended_posix_rename(u_int32_t id);
static void process_extended_statvfs(u_int32_t id);
static void process_extended_fstatvfs(u_int32_t id);
static void process_extended_hardlink(u_int32_t id);
static void process_extended_fsync(u_int32_t id);
+static void process_extended_lsetstat(u_int32_t id);
static void process_extended(u_int32_t id);
struct sftp_handler {
const char *name; /* user-visible name for fine-grained perms */
const char *ext_name; /* extended request name */
u_int type; /* packet type, for non extended packets */
void (*handler)(u_int32_t);
int does_write; /* if nonzero, banned for readonly mode */
};
-struct sftp_handler handlers[] = {
+static const struct sftp_handler handlers[] = {
/* NB. SSH2_FXP_OPEN does the readonly check in the handler itself */
{ "open", NULL, SSH2_FXP_OPEN, process_open, 0 },
{ "close", NULL, SSH2_FXP_CLOSE, process_close, 0 },
{ "read", NULL, SSH2_FXP_READ, process_read, 0 },
{ "write", NULL, SSH2_FXP_WRITE, process_write, 1 },
{ "lstat", NULL, SSH2_FXP_LSTAT, process_lstat, 0 },
{ "fstat", NULL, SSH2_FXP_FSTAT, process_fstat, 0 },
{ "setstat", NULL, SSH2_FXP_SETSTAT, process_setstat, 1 },
{ "fsetstat", NULL, SSH2_FXP_FSETSTAT, process_fsetstat, 1 },
{ "opendir", NULL, SSH2_FXP_OPENDIR, process_opendir, 0 },
{ "readdir", NULL, SSH2_FXP_READDIR, process_readdir, 0 },
{ "remove", NULL, SSH2_FXP_REMOVE, process_remove, 1 },
{ "mkdir", NULL, SSH2_FXP_MKDIR, process_mkdir, 1 },
{ "rmdir", NULL, SSH2_FXP_RMDIR, process_rmdir, 1 },
{ "realpath", NULL, SSH2_FXP_REALPATH, process_realpath, 0 },
{ "stat", NULL, SSH2_FXP_STAT, process_stat, 0 },
{ "rename", NULL, SSH2_FXP_RENAME, process_rename, 1 },
{ "readlink", NULL, SSH2_FXP_READLINK, process_readlink, 0 },
{ "symlink", NULL, SSH2_FXP_SYMLINK, process_symlink, 1 },
{ NULL, NULL, 0, NULL, 0 }
};
/* SSH2_FXP_EXTENDED submessages */
-struct sftp_handler extended_handlers[] = {
+static const struct sftp_handler extended_handlers[] = {
{ "posix-rename", "posix-rename@openssh.com", 0,
process_extended_posix_rename, 1 },
{ "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs, 0 },
{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 },
{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 },
{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 },
+ { "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 },
{ NULL, NULL, 0, NULL, 0 }
};
static int
-request_permitted(struct sftp_handler *h)
+request_permitted(const struct sftp_handler *h)
{
char *result;
if (readonly && h->does_write) {
verbose("Refusing %s request in read-only mode", h->name);
return 0;
}
if (request_blacklist != NULL &&
((result = match_list(h->name, request_blacklist, NULL))) != NULL) {
free(result);
verbose("Refusing blacklisted %s request", h->name);
return 0;
}
if (request_whitelist != NULL &&
((result = match_list(h->name, request_whitelist, NULL))) != NULL) {
free(result);
debug2("Permitting whitelisted %s request", h->name);
return 1;
}
if (request_whitelist != NULL) {
verbose("Refusing non-whitelisted %s request", h->name);
return 0;
}
return 1;
}
static int
errno_to_portable(int unixerrno)
{
int ret = 0;
switch (unixerrno) {
case 0:
ret = SSH2_FX_OK;
break;
case ENOENT:
case ENOTDIR:
case EBADF:
case ELOOP:
ret = SSH2_FX_NO_SUCH_FILE;
break;
case EPERM:
case EACCES:
case EFAULT:
ret = SSH2_FX_PERMISSION_DENIED;
break;
case ENAMETOOLONG:
case EINVAL:
ret = SSH2_FX_BAD_MESSAGE;
break;
case ENOSYS:
ret = SSH2_FX_OP_UNSUPPORTED;
break;
default:
ret = SSH2_FX_FAILURE;
break;
}
return ret;
}
static int
flags_from_portable(int pflags)
{
int flags = 0;
if ((pflags & SSH2_FXF_READ) &&
(pflags & SSH2_FXF_WRITE)) {
flags = O_RDWR;
} else if (pflags & SSH2_FXF_READ) {
flags = O_RDONLY;
} else if (pflags & SSH2_FXF_WRITE) {
flags = O_WRONLY;
}
if (pflags & SSH2_FXF_APPEND)
flags |= O_APPEND;
if (pflags & SSH2_FXF_CREAT)
flags |= O_CREAT;
if (pflags & SSH2_FXF_TRUNC)
flags |= O_TRUNC;
if (pflags & SSH2_FXF_EXCL)
flags |= O_EXCL;
return flags;
}
static const char *
string_from_portable(int pflags)
{
static char ret[128];
*ret = '\0';
#define PAPPEND(str) { \
if (*ret != '\0') \
strlcat(ret, ",", sizeof(ret)); \
strlcat(ret, str, sizeof(ret)); \
}
if (pflags & SSH2_FXF_READ)
PAPPEND("READ")
if (pflags & SSH2_FXF_WRITE)
PAPPEND("WRITE")
if (pflags & SSH2_FXF_APPEND)
PAPPEND("APPEND")
if (pflags & SSH2_FXF_CREAT)
PAPPEND("CREATE")
if (pflags & SSH2_FXF_TRUNC)
PAPPEND("TRUNCATE")
if (pflags & SSH2_FXF_EXCL)
PAPPEND("EXCL")
return ret;
}
/* handle handles */
typedef struct Handle Handle;
struct Handle {
int use;
DIR *dirp;
int fd;
int flags;
char *name;
u_int64_t bytes_read, bytes_write;
int next_unused;
};
enum {
HANDLE_UNUSED,
HANDLE_DIR,
HANDLE_FILE
};
-Handle *handles = NULL;
-u_int num_handles = 0;
-int first_unused_handle = -1;
+static Handle *handles = NULL;
+static u_int num_handles = 0;
+static int first_unused_handle = -1;
static void handle_unused(int i)
{
handles[i].use = HANDLE_UNUSED;
handles[i].next_unused = first_unused_handle;
first_unused_handle = i;
}
static int
handle_new(int use, const char *name, int fd, int flags, DIR *dirp)
{
int i;
if (first_unused_handle == -1) {
if (num_handles + 1 <= num_handles)
return -1;
num_handles++;
handles = xreallocarray(handles, num_handles, sizeof(Handle));
handle_unused(num_handles - 1);
}
i = first_unused_handle;
first_unused_handle = handles[i].next_unused;
handles[i].use = use;
handles[i].dirp = dirp;
handles[i].fd = fd;
handles[i].flags = flags;
handles[i].name = xstrdup(name);
handles[i].bytes_read = handles[i].bytes_write = 0;
return i;
}
static int
handle_is_ok(int i, int type)
{
return i >= 0 && (u_int)i < num_handles && handles[i].use == type;
}
static int
handle_to_string(int handle, u_char **stringp, int *hlenp)
{
if (stringp == NULL || hlenp == NULL)
return -1;
*stringp = xmalloc(sizeof(int32_t));
put_u32(*stringp, handle);
*hlenp = sizeof(int32_t);
return 0;
}
static int
handle_from_string(const u_char *handle, u_int hlen)
{
int val;
if (hlen != sizeof(int32_t))
return -1;
val = get_u32(handle);
if (handle_is_ok(val, HANDLE_FILE) ||
handle_is_ok(val, HANDLE_DIR))
return val;
return -1;
}
static char *
handle_to_name(int handle)
{
if (handle_is_ok(handle, HANDLE_DIR)||
handle_is_ok(handle, HANDLE_FILE))
return handles[handle].name;
return NULL;
}
static DIR *
handle_to_dir(int handle)
{
if (handle_is_ok(handle, HANDLE_DIR))
return handles[handle].dirp;
return NULL;
}
static int
handle_to_fd(int handle)
{
if (handle_is_ok(handle, HANDLE_FILE))
return handles[handle].fd;
return -1;
}
static int
handle_to_flags(int handle)
{
if (handle_is_ok(handle, HANDLE_FILE))
return handles[handle].flags;
return 0;
}
static void
handle_update_read(int handle, ssize_t bytes)
{
if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
handles[handle].bytes_read += bytes;
}
static void
handle_update_write(int handle, ssize_t bytes)
{
if (handle_is_ok(handle, HANDLE_FILE) && bytes > 0)
handles[handle].bytes_write += bytes;
}
static u_int64_t
handle_bytes_read(int handle)
{
if (handle_is_ok(handle, HANDLE_FILE))
return (handles[handle].bytes_read);
return 0;
}
static u_int64_t
handle_bytes_write(int handle)
{
if (handle_is_ok(handle, HANDLE_FILE))
return (handles[handle].bytes_write);
return 0;
}
static int
handle_close(int handle)
{
int ret = -1;
if (handle_is_ok(handle, HANDLE_FILE)) {
ret = close(handles[handle].fd);
free(handles[handle].name);
handle_unused(handle);
} else if (handle_is_ok(handle, HANDLE_DIR)) {
ret = closedir(handles[handle].dirp);
free(handles[handle].name);
handle_unused(handle);
} else {
errno = ENOENT;
}
return ret;
}
static void
handle_log_close(int handle, char *emsg)
{
if (handle_is_ok(handle, HANDLE_FILE)) {
logit("%s%sclose \"%s\" bytes read %llu written %llu",
emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
handle_to_name(handle),
(unsigned long long)handle_bytes_read(handle),
(unsigned long long)handle_bytes_write(handle));
} else {
logit("%s%sclosedir \"%s\"",
emsg == NULL ? "" : emsg, emsg == NULL ? "" : " ",
handle_to_name(handle));
}
}
static void
handle_log_exit(void)
{
u_int i;
for (i = 0; i < num_handles; i++)
if (handles[i].use != HANDLE_UNUSED)
handle_log_close(i, "forced");
}
static int
get_handle(struct sshbuf *queue, int *hp)
{
u_char *handle;
int r;
size_t hlen;
*hp = -1;
if ((r = sshbuf_get_string(queue, &handle, &hlen)) != 0)
return r;
if (hlen < 256)
*hp = handle_from_string(handle, hlen);
free(handle);
return 0;
}
/* send replies */
static void
send_msg(struct sshbuf *m)
{
int r;
if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_reset(m);
}
static const char *
status_to_message(u_int32_t status)
{
const char *status_messages[] = {
"Success", /* SSH_FX_OK */
"End of file", /* SSH_FX_EOF */
"No such file", /* SSH_FX_NO_SUCH_FILE */
"Permission denied", /* SSH_FX_PERMISSION_DENIED */
"Failure", /* SSH_FX_FAILURE */
"Bad message", /* SSH_FX_BAD_MESSAGE */
"No connection", /* SSH_FX_NO_CONNECTION */
"Connection lost", /* SSH_FX_CONNECTION_LOST */
"Operation unsupported", /* SSH_FX_OP_UNSUPPORTED */
"Unknown error" /* Others */
};
return (status_messages[MINIMUM(status,SSH2_FX_MAX)]);
}
static void
send_status(u_int32_t id, u_int32_t status)
{
struct sshbuf *msg;
int r;
debug3("request %u: sent status %u", id, status);
if (log_level > SYSLOG_LEVEL_VERBOSE ||
(status != SSH2_FX_OK && status != SSH2_FX_EOF))
logit("sent status %s", status_to_message(status));
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_u32(msg, status)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (version >= 3) {
if ((r = sshbuf_put_cstring(msg,
status_to_message(status))) != 0 ||
(r = sshbuf_put_cstring(msg, "")) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
send_msg(msg);
sshbuf_free(msg);
}
static void
send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen)
{
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, data, dlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
sshbuf_free(msg);
}
static void
send_data(u_int32_t id, const u_char *data, int dlen)
{
debug("request %u: sent data len %d", id, dlen);
send_data_or_handle(SSH2_FXP_DATA, id, data, dlen);
}
static void
send_handle(u_int32_t id, int handle)
{
u_char *string;
int hlen;
handle_to_string(handle, &string, &hlen);
debug("request %u: sent handle handle %d", id, handle);
send_data_or_handle(SSH2_FXP_HANDLE, id, string, hlen);
free(string);
}
static void
send_names(u_int32_t id, int count, const Stat *stats)
{
struct sshbuf *msg;
int i, r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_u32(msg, count)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: sent names count %d", id, count);
for (i = 0; i < count; i++) {
if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 ||
(r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 ||
(r = encode_attrib(msg, &stats[i].attrib)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
send_msg(msg);
sshbuf_free(msg);
}
static void
send_attrib(u_int32_t id, const Attrib *a)
{
struct sshbuf *msg;
int r;
debug("request %u: sent attrib have 0x%x", id, a->flags);
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = encode_attrib(msg, a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
sshbuf_free(msg);
}
static void
send_statvfs(u_int32_t id, struct statvfs *st)
{
struct sshbuf *msg;
u_int64_t flag;
int r;
flag = (st->f_flag & ST_RDONLY) ? SSH2_FXE_STATVFS_ST_RDONLY : 0;
flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_bsize)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_frsize)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_blocks)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_bfree)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_bavail)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_files)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_ffree)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_favail)) != 0 ||
(r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 ||
(r = sshbuf_put_u64(msg, flag)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_namemax)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
sshbuf_free(msg);
}
/* parse incoming */
static void
process_init(void)
{
struct sshbuf *msg;
int r;
if ((r = sshbuf_get_u32(iqueue, &version)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
verbose("received client version %u", version);
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 ||
(r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 ||
/* POSIX rename extension */
(r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
/* statvfs extension */
(r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
/* fstatvfs extension */
(r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
/* hardlink extension */
(r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
/* fsync extension */
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
+ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
sshbuf_free(msg);
}
static void
process_open(u_int32_t id)
{
u_int32_t pflags;
Attrib a;
char *name;
int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
(r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
((flags & O_ACCMODE) != O_RDONLY ||
(flags & (O_CREAT|O_TRUNC)) != 0)) {
verbose("Refusing open request in read-only mode");
status = SSH2_FX_PERMISSION_DENIED;
} else {
fd = open(name, flags, mode);
if (fd < 0) {
status = errno_to_portable(errno);
} else {
handle = handle_new(HANDLE_FILE, name, fd, flags, NULL);
if (handle < 0) {
close(fd);
} else {
send_handle(id, handle);
status = SSH2_FX_OK;
}
}
}
if (status != SSH2_FX_OK)
send_status(id, status);
free(name);
}
static void
process_close(u_int32_t id)
{
int r, handle, ret, status = SSH2_FX_FAILURE;
if ((r = get_handle(iqueue, &handle)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: close handle %u", id, handle);
handle_log_close(handle, NULL);
ret = handle_close(handle);
status = (ret == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
}
static void
process_read(u_int32_t id)
{
u_char buf[64*1024];
u_int32_t len;
int r, handle, fd, ret, status = SSH2_FX_FAILURE;
u_int64_t off;
if ((r = get_handle(iqueue, &handle)) != 0 ||
(r = sshbuf_get_u64(iqueue, &off)) != 0 ||
(r = sshbuf_get_u32(iqueue, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: read \"%s\" (handle %d) off %llu len %d",
id, handle_to_name(handle), handle, (unsigned long long)off, len);
if (len > sizeof buf) {
len = sizeof buf;
debug2("read change len %d", len);
}
fd = handle_to_fd(handle);
if (fd >= 0) {
if (lseek(fd, off, SEEK_SET) < 0) {
error("process_read: seek failed");
status = errno_to_portable(errno);
} else {
ret = read(fd, buf, len);
if (ret < 0) {
status = errno_to_portable(errno);
} else if (ret == 0) {
status = SSH2_FX_EOF;
} else {
send_data(id, buf, ret);
status = SSH2_FX_OK;
handle_update_read(handle, ret);
}
}
}
if (status != SSH2_FX_OK)
send_status(id, status);
}
static void
process_write(u_int32_t id)
{
u_int64_t off;
size_t len;
int r, handle, fd, ret, status;
u_char *data;
if ((r = get_handle(iqueue, &handle)) != 0 ||
(r = sshbuf_get_u64(iqueue, &off)) != 0 ||
(r = sshbuf_get_string(iqueue, &data, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
id, handle_to_name(handle), handle, (unsigned long long)off, len);
fd = handle_to_fd(handle);
if (fd < 0)
status = SSH2_FX_FAILURE;
else {
if (!(handle_to_flags(handle) & O_APPEND) &&
lseek(fd, off, SEEK_SET) < 0) {
status = errno_to_portable(errno);
error("process_write: seek failed");
} else {
/* XXX ATOMICIO ? */
ret = write(fd, data, len);
if (ret < 0) {
error("process_write: write failed");
status = errno_to_portable(errno);
} else if ((size_t)ret == len) {
status = SSH2_FX_OK;
handle_update_write(handle, ret);
} else {
debug2("nothing at all written");
status = SSH2_FX_FAILURE;
}
}
}
send_status(id, status);
free(data);
}
static void
process_do_stat(u_int32_t id, int do_lstat)
{
Attrib a;
struct stat st;
char *name;
int r, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: %sstat", id, do_lstat ? "l" : "");
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
r = do_lstat ? lstat(name, &st) : stat(name, &st);
if (r < 0) {
status = errno_to_portable(errno);
} else {
stat_to_attrib(&st, &a);
send_attrib(id, &a);
status = SSH2_FX_OK;
}
if (status != SSH2_FX_OK)
send_status(id, status);
free(name);
}
static void
process_stat(u_int32_t id)
{
process_do_stat(id, 0);
}
static void
process_lstat(u_int32_t id)
{
process_do_stat(id, 1);
}
static void
process_fstat(u_int32_t id)
{
Attrib a;
struct stat st;
int fd, r, handle, status = SSH2_FX_FAILURE;
if ((r = get_handle(iqueue, &handle)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: fstat \"%s\" (handle %u)",
id, handle_to_name(handle), handle);
fd = handle_to_fd(handle);
if (fd >= 0) {
r = fstat(fd, &st);
if (r < 0) {
status = errno_to_portable(errno);
} else {
stat_to_attrib(&st, &a);
send_attrib(id, &a);
status = SSH2_FX_OK;
}
}
if (status != SSH2_FX_OK)
send_status(id, status);
}
static struct timeval *
attrib_to_tv(const Attrib *a)
{
static struct timeval tv[2];
tv[0].tv_sec = a->atime;
tv[0].tv_usec = 0;
tv[1].tv_sec = a->mtime;
tv[1].tv_usec = 0;
return tv;
}
+static struct timespec *
+attrib_to_ts(const Attrib *a)
+{
+ static struct timespec ts[2];
+
+ ts[0].tv_sec = a->atime;
+ ts[0].tv_nsec = 0;
+ ts[1].tv_sec = a->mtime;
+ ts[1].tv_nsec = 0;
+ return ts;
+}
+
static void
process_setstat(u_int32_t id)
{
Attrib a;
char *name;
int r, status = SSH2_FX_OK;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: setstat name \"%s\"", id, name);
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
logit("set \"%s\" size %llu",
name, (unsigned long long)a.size);
r = truncate(name, a.size);
if (r == -1)
status = errno_to_portable(errno);
}
if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
logit("set \"%s\" mode %04o", name, a.perm);
r = chmod(name, a.perm & 07777);
if (r == -1)
status = errno_to_portable(errno);
}
if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
char buf[64];
time_t t = a.mtime;
strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
localtime(&t));
logit("set \"%s\" modtime %s", name, buf);
r = utimes(name, attrib_to_tv(&a));
if (r == -1)
status = errno_to_portable(errno);
}
if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
logit("set \"%s\" owner %lu group %lu", name,
(u_long)a.uid, (u_long)a.gid);
r = chown(name, a.uid, a.gid);
if (r == -1)
status = errno_to_portable(errno);
}
send_status(id, status);
free(name);
}
static void
process_fsetstat(u_int32_t id)
{
Attrib a;
int handle, fd, r;
int status = SSH2_FX_OK;
if ((r = get_handle(iqueue, &handle)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: fsetstat handle %d", id, handle);
fd = handle_to_fd(handle);
if (fd < 0)
status = SSH2_FX_FAILURE;
else {
char *name = handle_to_name(handle);
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
logit("set \"%s\" size %llu",
name, (unsigned long long)a.size);
r = ftruncate(fd, a.size);
if (r == -1)
status = errno_to_portable(errno);
}
if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
logit("set \"%s\" mode %04o", name, a.perm);
#ifdef HAVE_FCHMOD
r = fchmod(fd, a.perm & 07777);
#else
r = chmod(name, a.perm & 07777);
#endif
if (r == -1)
status = errno_to_portable(errno);
}
if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
char buf[64];
time_t t = a.mtime;
strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
localtime(&t));
logit("set \"%s\" modtime %s", name, buf);
#ifdef HAVE_FUTIMES
r = futimes(fd, attrib_to_tv(&a));
#else
r = utimes(name, attrib_to_tv(&a));
#endif
if (r == -1)
status = errno_to_portable(errno);
}
if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
logit("set \"%s\" owner %lu group %lu", name,
(u_long)a.uid, (u_long)a.gid);
#ifdef HAVE_FCHOWN
r = fchown(fd, a.uid, a.gid);
#else
r = chown(name, a.uid, a.gid);
#endif
if (r == -1)
status = errno_to_portable(errno);
}
}
send_status(id, status);
}
static void
process_opendir(u_int32_t id)
{
DIR *dirp = NULL;
char *path;
int r, handle, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: opendir", id);
logit("opendir \"%s\"", path);
dirp = opendir(path);
if (dirp == NULL) {
status = errno_to_portable(errno);
} else {
handle = handle_new(HANDLE_DIR, path, 0, 0, dirp);
if (handle < 0) {
closedir(dirp);
} else {
send_handle(id, handle);
status = SSH2_FX_OK;
}
}
if (status != SSH2_FX_OK)
send_status(id, status);
free(path);
}
static void
process_readdir(u_int32_t id)
{
DIR *dirp;
struct dirent *dp;
char *path;
int r, handle;
if ((r = get_handle(iqueue, &handle)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: readdir \"%s\" (handle %d)", id,
handle_to_name(handle), handle);
dirp = handle_to_dir(handle);
path = handle_to_name(handle);
if (dirp == NULL || path == NULL) {
send_status(id, SSH2_FX_FAILURE);
} else {
struct stat st;
char pathname[PATH_MAX];
Stat *stats;
int nstats = 10, count = 0, i;
stats = xcalloc(nstats, sizeof(Stat));
while ((dp = readdir(dirp)) != NULL) {
if (count >= nstats) {
nstats *= 2;
stats = xreallocarray(stats, nstats, sizeof(Stat));
}
/* XXX OVERFLOW ? */
snprintf(pathname, sizeof pathname, "%s%s%s", path,
strcmp(path, "/") ? "/" : "", dp->d_name);
if (lstat(pathname, &st) < 0)
continue;
stat_to_attrib(&st, &(stats[count].attrib));
stats[count].name = xstrdup(dp->d_name);
stats[count].long_name = ls_file(dp->d_name, &st, 0, 0);
count++;
/* send up to 100 entries in one message */
/* XXX check packet size instead */
if (count == 100)
break;
}
if (count > 0) {
send_names(id, count, stats);
for (i = 0; i < count; i++) {
free(stats[i].name);
free(stats[i].long_name);
}
} else {
send_status(id, SSH2_FX_EOF);
}
free(stats);
}
}
static void
process_remove(u_int32_t id)
{
char *name;
int r, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: remove", id);
logit("remove name \"%s\"", name);
r = unlink(name);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
free(name);
}
static void
process_mkdir(u_int32_t id)
{
Attrib a;
char *name;
int r, mode, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
a.perm & 07777 : 0777;
debug3("request %u: mkdir", id);
logit("mkdir name \"%s\" mode 0%o", name, mode);
r = mkdir(name, mode);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
free(name);
}
static void
process_rmdir(u_int32_t id)
{
char *name;
int r, status;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: rmdir", id);
logit("rmdir name \"%s\"", name);
r = rmdir(name);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
free(name);
}
static void
process_realpath(u_int32_t id)
{
char resolvedname[PATH_MAX];
char *path;
int r;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (path[0] == '\0') {
free(path);
path = xstrdup(".");
}
debug3("request %u: realpath", id);
verbose("realpath \"%s\"", path);
if (realpath(path, resolvedname) == NULL) {
send_status(id, errno_to_portable(errno));
} else {
Stat s;
attrib_clear(&s.attrib);
s.name = s.long_name = resolvedname;
send_names(id, 1, &s);
}
free(path);
}
static void
process_rename(u_int32_t id)
{
char *oldpath, *newpath;
int r, status;
struct stat sb;
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: rename", id);
logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
status = SSH2_FX_FAILURE;
if (lstat(oldpath, &sb) == -1)
status = errno_to_portable(errno);
else if (S_ISREG(sb.st_mode)) {
/* Race-free rename of regular files */
if (link(oldpath, newpath) == -1) {
if (errno == EOPNOTSUPP || errno == ENOSYS
#ifdef EXDEV
|| errno == EXDEV
#endif
#ifdef LINK_OPNOTSUPP_ERRNO
|| errno == LINK_OPNOTSUPP_ERRNO
#endif
) {
struct stat st;
/*
* fs doesn't support links, so fall back to
* stat+rename. This is racy.
*/
if (stat(newpath, &st) == -1) {
if (rename(oldpath, newpath) == -1)
status =
errno_to_portable(errno);
else
status = SSH2_FX_OK;
}
} else {
status = errno_to_portable(errno);
}
} else if (unlink(oldpath) == -1) {
status = errno_to_portable(errno);
/* clean spare link */
unlink(newpath);
} else
status = SSH2_FX_OK;
} else if (stat(newpath, &sb) == -1) {
if (rename(oldpath, newpath) == -1)
status = errno_to_portable(errno);
else
status = SSH2_FX_OK;
}
send_status(id, status);
free(oldpath);
free(newpath);
}
static void
process_readlink(u_int32_t id)
{
int r, len;
char buf[PATH_MAX];
char *path;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: readlink", id);
verbose("readlink \"%s\"", path);
if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1)
send_status(id, errno_to_portable(errno));
else {
Stat s;
buf[len] = '\0';
attrib_clear(&s.attrib);
s.name = s.long_name = buf;
send_names(id, 1, &s);
}
free(path);
}
static void
process_symlink(u_int32_t id)
{
char *oldpath, *newpath;
int r, status;
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: symlink", id);
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
/* this will fail if 'newpath' exists */
r = symlink(oldpath, newpath);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
free(oldpath);
free(newpath);
}
static void
process_extended_posix_rename(u_int32_t id)
{
char *oldpath, *newpath;
int r, status;
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: posix-rename", id);
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
r = rename(oldpath, newpath);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
free(oldpath);
free(newpath);
}
static void
process_extended_statvfs(u_int32_t id)
{
char *path;
struct statvfs st;
int r;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: statvfs", id);
logit("statvfs \"%s\"", path);
if (statvfs(path, &st) != 0)
send_status(id, errno_to_portable(errno));
else
send_statvfs(id, &st);
free(path);
}
static void
process_extended_fstatvfs(u_int32_t id)
{
int r, handle, fd;
struct statvfs st;
if ((r = get_handle(iqueue, &handle)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("request %u: fstatvfs \"%s\" (handle %u)",
id, handle_to_name(handle), handle);
if ((fd = handle_to_fd(handle)) < 0) {
send_status(id, SSH2_FX_FAILURE);
return;
}
if (fstatvfs(fd, &st) != 0)
send_status(id, errno_to_portable(errno));
else
send_statvfs(id, &st);
}
static void
process_extended_hardlink(u_int32_t id)
{
char *oldpath, *newpath;
int r, status;
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: hardlink", id);
logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
r = link(oldpath, newpath);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
send_status(id, status);
free(oldpath);
free(newpath);
}
static void
process_extended_fsync(u_int32_t id)
{
int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
if ((r = get_handle(iqueue, &handle)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug3("request %u: fsync (handle %u)", id, handle);
verbose("fsync \"%s\"", handle_to_name(handle));
if ((fd = handle_to_fd(handle)) < 0)
status = SSH2_FX_NO_SUCH_FILE;
else if (handle_is_ok(handle, HANDLE_FILE)) {
r = fsync(fd);
status = (r == -1) ? errno_to_portable(errno) : SSH2_FX_OK;
}
send_status(id, status);
}
+static void
+process_extended_lsetstat(u_int32_t id)
+{
+ Attrib a;
+ char *name;
+ int r, status = SSH2_FX_OK;
+
+ if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
+ (r = decode_attrib(iqueue, &a)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ debug("request %u: lsetstat name \"%s\"", id, name);
+ if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
+ /* nonsensical for links */
+ status = SSH2_FX_BAD_MESSAGE;
+ goto out;
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
+ logit("set \"%s\" mode %04o", name, a.perm);
+ r = fchmodat(AT_FDCWD, name,
+ a.perm & 07777, AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ status = errno_to_portable(errno);
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
+ char buf[64];
+ time_t t = a.mtime;
+
+ strftime(buf, sizeof(buf), "%Y%m%d-%H:%M:%S",
+ localtime(&t));
+ logit("set \"%s\" modtime %s", name, buf);
+ r = utimensat(AT_FDCWD, name,
+ attrib_to_ts(&a), AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ status = errno_to_portable(errno);
+ }
+ if (a.flags & SSH2_FILEXFER_ATTR_UIDGID) {
+ logit("set \"%s\" owner %lu group %lu", name,
+ (u_long)a.uid, (u_long)a.gid);
+ r = fchownat(AT_FDCWD, name, a.uid, a.gid,
+ AT_SYMLINK_NOFOLLOW);
+ if (r == -1)
+ status = errno_to_portable(errno);
+ }
+ out:
+ send_status(id, status);
+ free(name);
+}
+
static void
process_extended(u_int32_t id)
{
char *request;
int i, r;
if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; extended_handlers[i].handler != NULL; i++) {
if (strcmp(request, extended_handlers[i].ext_name) == 0) {
if (!request_permitted(&extended_handlers[i]))
send_status(id, SSH2_FX_PERMISSION_DENIED);
else
extended_handlers[i].handler(id);
break;
}
}
if (extended_handlers[i].handler == NULL) {
error("Unknown extended request \"%.100s\"", request);
send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
}
free(request);
}
/* stolen from ssh-agent */
static void
process(void)
{
u_int msg_len;
u_int buf_len;
u_int consumed;
u_char type;
const u_char *cp;
int i, r;
u_int32_t id;
buf_len = sshbuf_len(iqueue);
if (buf_len < 5)
return; /* Incomplete message. */
cp = sshbuf_ptr(iqueue);
msg_len = get_u32(cp);
if (msg_len > SFTP_MAX_MSG_LENGTH) {
error("bad message from %s local user %s",
client_addr, pw->pw_name);
sftp_server_cleanup_exit(11);
}
if (buf_len < msg_len + 4)
return;
if ((r = sshbuf_consume(iqueue, 4)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
buf_len -= 4;
if ((r = sshbuf_get_u8(iqueue, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
switch (type) {
case SSH2_FXP_INIT:
process_init();
init_done = 1;
break;
case SSH2_FXP_EXTENDED:
if (!init_done)
fatal("Received extended request before init");
if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
process_extended(id);
break;
default:
if (!init_done)
fatal("Received %u request before init", type);
if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; handlers[i].handler != NULL; i++) {
if (type == handlers[i].type) {
if (!request_permitted(&handlers[i])) {
send_status(id,
SSH2_FX_PERMISSION_DENIED);
} else {
handlers[i].handler(id);
}
break;
}
}
if (handlers[i].handler == NULL)
error("Unknown message %u", type);
}
/* discard the remaining bytes from the current packet */
if (buf_len < sshbuf_len(iqueue)) {
error("iqueue grew unexpectedly");
sftp_server_cleanup_exit(255);
}
consumed = buf_len - sshbuf_len(iqueue);
if (msg_len < consumed) {
error("msg_len %u < consumed %u", msg_len, consumed);
sftp_server_cleanup_exit(255);
}
if (msg_len > consumed &&
(r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* Cleanup handler that logs active handles upon normal exit */
void
sftp_server_cleanup_exit(int i)
{
if (pw != NULL && client_addr != NULL) {
handle_log_exit();
logit("session closed for local user %s from [%s]",
pw->pw_name, client_addr);
}
_exit(i);
}
static void
sftp_server_usage(void)
{
extern char *__progname;
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-P blacklisted_requests] "
"[-p whitelisted_requests] [-u umask]\n"
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
}
int
sftp_server_main(int argc, char **argv, struct passwd *user_pw)
{
fd_set *rset, *wset;
int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
ssize_t len, olen, set_size;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
char *cp, *homedir = NULL, uidstr[32], buf[4*4096];
long mask;
extern char *optarg;
extern char *__progname;
ssh_malloc_init(); /* must be called before any mallocs */
__progname = ssh_get_progname(argv[0]);
log_init(__progname, log_level, log_facility, log_stderr);
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
"d:f:l:P:p:Q:u:cehR")) != -1) {
switch (ch) {
case 'Q':
if (strcasecmp(optarg, "requests") != 0) {
fprintf(stderr, "Invalid query type\n");
exit(1);
}
for (i = 0; handlers[i].handler != NULL; i++)
printf("%s\n", handlers[i].name);
for (i = 0; extended_handlers[i].handler != NULL; i++)
printf("%s\n", extended_handlers[i].name);
exit(0);
break;
case 'R':
readonly = 1;
break;
case 'c':
/*
* Ignore all arguments if we are invoked as a
* shell using "sftp-server -c command"
*/
skipargs = 1;
break;
case 'e':
log_stderr = 1;
break;
case 'l':
log_level = log_level_number(optarg);
if (log_level == SYSLOG_LEVEL_NOT_SET)
error("Invalid log level \"%s\"", optarg);
break;
case 'f':
log_facility = log_facility_number(optarg);
if (log_facility == SYSLOG_FACILITY_NOT_SET)
error("Invalid log facility \"%s\"", optarg);
break;
case 'd':
cp = tilde_expand_filename(optarg, user_pw->pw_uid);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
homedir = percent_expand(cp, "d", user_pw->pw_dir,
"u", user_pw->pw_name, "U", uidstr, (char *)NULL);
free(cp);
break;
case 'p':
if (request_whitelist != NULL)
fatal("Permitted requests already set");
request_whitelist = xstrdup(optarg);
break;
case 'P':
if (request_blacklist != NULL)
fatal("Refused requests already set");
request_blacklist = xstrdup(optarg);
break;
case 'u':
errno = 0;
mask = strtol(optarg, &cp, 8);
if (mask < 0 || mask > 0777 || *cp != '\0' ||
cp == optarg || (mask == 0 && errno != 0))
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;
case 'h':
default:
sftp_server_usage();
}
}
log_init(__progname, log_level, log_facility, log_stderr);
/*
* On platforms where we can, avoid making /proc/self/{mem,maps}
* available to the user so that sftp access doesn't automatically
* imply arbitrary code execution access that will break
* restricted configurations.
*/
platform_disable_tracing(1); /* strict */
/* Drop any fine-grained privileges we don't need */
platform_pledge_sftp_server();
if ((cp = getenv("SSH_CONNECTION")) != NULL) {
client_addr = xstrdup(cp);
if ((cp = strchr(client_addr, ' ')) == NULL) {
error("Malformed SSH_CONNECTION variable: \"%s\"",
getenv("SSH_CONNECTION"));
sftp_server_cleanup_exit(255);
}
*cp = '\0';
} else
client_addr = xstrdup("UNKNOWN");
logit("session opened for local user %s from [%s]",
pw->pw_name, client_addr);
in = STDIN_FILENO;
out = STDOUT_FILENO;
#ifdef HAVE_CYGWIN
setmode(in, O_BINARY);
setmode(out, O_BINARY);
#endif
max = 0;
if (in > max)
max = in;
if (out > max)
max = out;
if ((iqueue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((oqueue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
if (homedir != NULL) {
if (chdir(homedir) != 0) {
error("chdir to \"%s\" failed: %s", homedir,
strerror(errno));
}
}
set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
for (;;) {
memset(rset, 0, set_size);
memset(wset, 0, set_size);
/*
* Ensure that we can read a full buffer and handle
* the worst-case length packet it can generate,
* otherwise apply backpressure by stopping reads.
*/
if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
(r = sshbuf_check_reserve(oqueue,
SFTP_MAX_MSG_LENGTH)) == 0)
FD_SET(in, rset);
else if (r != SSH_ERR_NO_BUFFER_SPACE)
fatal("%s: sshbuf_check_reserve failed: %s",
__func__, ssh_err(r));
olen = sshbuf_len(oqueue);
if (olen > 0)
FD_SET(out, wset);
if (select(max+1, rset, wset, NULL, NULL) < 0) {
if (errno == EINTR)
continue;
error("select: %s", strerror(errno));
sftp_server_cleanup_exit(2);
}
/* copy stdin to iqueue */
if (FD_ISSET(in, rset)) {
len = read(in, buf, sizeof buf);
if (len == 0) {
debug("read eof");
sftp_server_cleanup_exit(0);
} else if (len < 0) {
error("read: %s", strerror(errno));
sftp_server_cleanup_exit(1);
} else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
/* send oqueue to stdout */
if (FD_ISSET(out, wset)) {
len = write(out, sshbuf_ptr(oqueue), olen);
if (len < 0) {
error("write: %s", strerror(errno));
sftp_server_cleanup_exit(1);
} else if ((r = sshbuf_consume(oqueue, len)) != 0) {
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
/*
* Process requests from client if we can fit the results
* into the output buffer, otherwise stop processing input
* and let the output queue drain.
*/
r = sshbuf_check_reserve(oqueue, SFTP_MAX_MSG_LENGTH);
if (r == 0)
process();
else if (r != SSH_ERR_NO_BUFFER_SPACE)
fatal("%s: sshbuf_check_reserve: %s",
__func__, ssh_err(r));
}
}
diff --git a/sftp.0 b/sftp.0
index ed98400d3ead..2342c2320fbd 100644
--- a/sftp.0
+++ b/sftp.0
@@ -1,379 +1,396 @@
SFTP(1) General Commands Manual SFTP(1)
NAME
sftp M-bM-^@M-^S secure file transfer program
SYNOPSIS
sftp [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]
- [-D sftp_server_path] [-F ssh_config] [-i identity_file] [-l limit]
- [-o ssh_option] [-P port] [-R num_requests] [-S program]
- [-s subsystem | sftp_server] destination
+ [-D sftp_server_path] [-F ssh_config] [-i identity_file]
+ [-J destination] [-l limit] [-o ssh_option] [-P port]
+ [-R num_requests] [-S program] [-s subsystem | sftp_server]
+ destination
DESCRIPTION
sftp is a file transfer program, similar to ftp(1), which performs all
operations over an encrypted ssh(1) transport. It may also use many
features of ssh, such as public key authentication and compression.
The destination may be specified either as [user@]host[:path] or as a URI
in the form sftp://[user@]host[:port][/path].
If the destination includes a path and it is not a directory, sftp will
retrieve files automatically if a non-interactive authentication method
is used; otherwise it will do so after successful interactive
authentication.
If no path is specified, or if the path is a directory, sftp will log in
to the specified host and enter interactive command mode, changing to the
remote directory if one was specified. An optional trailing slash can be
used to force the path to be interpreted as a directory.
Since the destination formats use colon characters to delimit host names
from path names or port numbers, IPv6 addresses must be enclosed in
square brackets to avoid ambiguity.
The options are as follows:
-4 Forces sftp to use IPv4 addresses only.
-6 Forces sftp to use IPv6 addresses only.
-a Attempt to continue interrupted transfers rather than overwriting
existing partial or complete copies of files. If the partial
contents differ from those being transferred, then the resultant
file is likely to be corrupt.
-B buffer_size
Specify the size of the buffer that sftp uses when transferring
files. Larger buffers require fewer round trips at the cost of
higher memory consumption. The default is 32768 bytes.
-b batchfile
Batch mode reads a series of commands from an input batchfile
instead of stdin. Since it lacks user interaction it should be
used in conjunction with non-interactive authentication to
obviate the need to enter a password at connection time (see
- sshd(8) and ssh-keygen(1) for details). A batchfile of M-bM-^@M-^X-M-bM-^@M-^Y may
- be used to indicate standard input. sftp will abort if any of
- the following commands fail: get, put, reget, reput, rename, ln,
- rm, mkdir, chdir, ls, lchdir, chmod, chown, chgrp, lpwd, df,
- symlink, and lmkdir. Termination on error can be suppressed on a
- command by command basis by prefixing the command with a M-bM-^@M-^X-M-bM-^@M-^Y
- character (for example, -rm /tmp/blah*).
+ sshd(8) and ssh-keygen(1) for details).
+
+ A batchfile of M-bM-^@M-^X-M-bM-^@M-^Y may be used to indicate standard input. sftp
+ will abort if any of the following commands fail: get, put,
+ reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod,
+ chown, chgrp, lpwd, df, symlink, and lmkdir.
+
+ Termination on error can be suppressed on a command by command
+ basis by prefixing the command with a M-bM-^@M-^X-M-bM-^@M-^Y character (for example,
+ -rm /tmp/blah*). Echo of the command may be suppressed by
+ prefixing the command with a M-bM-^@M-^X@M-bM-^@M-^Y character. These two prefixes
+ may be combined in any order, for example -@ls /bsd.
-C Enables compression (via ssh's -C flag).
-c cipher
Selects the cipher to use for encrypting the data transfers.
This option is directly passed to ssh(1).
-D sftp_server_path
Connect directly to a local sftp server (rather than via ssh(1)).
This option may be useful in debugging the client and server.
-F ssh_config
Specifies an alternative per-user configuration file for ssh(1).
This option is directly passed to ssh(1).
-f Requests that files be flushed to disk immediately after
transfer. When uploading files, this feature is only enabled if
the server implements the "fsync@openssh.com" extension.
-i identity_file
Selects the file from which the identity (private key) for public
key authentication is read. This option is directly passed to
ssh(1).
+ -J destination
+ Connect to the target host by first making an sftp connection to
+ the jump host described by destination and then establishing a
+ TCP forwarding to the ultimate destination from there. Multiple
+ jump hops may be specified separated by comma characters. This
+ is a shortcut to specify a ProxyJump configuration directive.
+ This option is directly passed to ssh(1).
+
-l limit
Limits the used bandwidth, specified in Kbit/s.
-o ssh_option
Can be used to pass options to ssh in the format used in
ssh_config(5). This is useful for specifying options for which
there is no separate sftp command-line flag. For example, to
specify an alternate port use: sftp -oPort=24. For full details
of the options listed below, and their possible values, see
ssh_config(5).
AddressFamily
BatchMode
BindAddress
BindInterface
CanonicalDomains
CanonicalizeFallbackLocal
CanonicalizeHostname
CanonicalizeMaxDots
CanonicalizePermittedCNAMEs
CASignatureAlgorithms
CertificateFile
ChallengeResponseAuthentication
CheckHostIP
Ciphers
Compression
ConnectionAttempts
ConnectTimeout
ControlMaster
ControlPath
ControlPersist
GlobalKnownHostsFile
GSSAPIAuthentication
GSSAPIDelegateCredentials
HashKnownHosts
Host
HostbasedAuthentication
HostbasedKeyTypes
HostKeyAlgorithms
HostKeyAlias
HostName
IdentitiesOnly
IdentityAgent
IdentityFile
IPQoS
KbdInteractiveAuthentication
KbdInteractiveDevices
KexAlgorithms
LogLevel
MACs
NoHostAuthenticationForLocalhost
NumberOfPasswordPrompts
PasswordAuthentication
PKCS11Provider
Port
PreferredAuthentications
ProxyCommand
ProxyJump
PubkeyAcceptedKeyTypes
PubkeyAuthentication
RekeyLimit
SendEnv
ServerAliveInterval
ServerAliveCountMax
SetEnv
StrictHostKeyChecking
TCPKeepAlive
UpdateHostKeys
User
UserKnownHostsFile
VerifyHostKeyDNS
-P port
Specifies the port to connect to on the remote host.
-p Preserves modification times, access times, and modes from the
original files transferred.
-q Quiet mode: disables the progress meter as well as warning and
diagnostic messages from ssh(1).
-R num_requests
Specify how many requests may be outstanding at any one time.
Increasing this may slightly improve file transfer speed but will
increase memory usage. The default is 64 outstanding requests.
-r Recursively copy entire directories when uploading and
downloading. Note that sftp does not follow symbolic links
encountered in the tree traversal.
-S program
Name of the program to use for the encrypted connection. The
program must understand ssh(1) options.
-s subsystem | sftp_server
Specifies the SSH2 subsystem or the path for an sftp server on
the remote host. A path is useful when the remote sshd(8) does
not have an sftp subsystem configured.
-v Raise logging level. This option is also passed to ssh.
INTERACTIVE COMMANDS
Once in interactive mode, sftp understands a set of commands similar to
those of ftp(1). Commands are case insensitive. Pathnames that contain
spaces must be enclosed in quotes. Any special characters contained
within pathnames that are recognized by glob(3) must be escaped with
backslashes (M-bM-^@M-^X\M-bM-^@M-^Y).
bye Quit sftp.
cd [path]
Change remote directory to path. If path is not specified, then
change directory to the one the session started in.
- chgrp grp path
- Change group of file path to grp. path may contain glob(7)
+ chgrp [-h] grp path
+ Change group of file path to grp. If the -h flag is specified,
+ then symlinks will not be followed. path may contain glob(7)
characters and may match multiple files. grp must be a numeric
GID.
- chmod mode path
- Change permissions of file path to mode. path may contain
+ chmod [-h] mode path
+ Change permissions of file path to mode. If the -h flag is
+ specified, then symlinks will not be followed. path may contain
glob(7) characters and may match multiple files.
- chown own path
- Change owner of file path to own. path may contain glob(7)
+ chown [-h] own path
+ Change owner of file path to own. If the -h flag is specified,
+ then symlinks will not be followed. path may contain glob(7)
characters and may match multiple files. own must be a numeric
UID.
df [-hi] [path]
Display usage information for the filesystem holding the current
directory (or path if specified). If the -h flag is specified,
the capacity information will be displayed using "human-readable"
suffixes. The -i flag requests display of inode information in
addition to capacity information. This command is only supported
on servers that implement the M-bM-^@M-^\statvfs@openssh.comM-bM-^@M-^] extension.
exit Quit sftp.
get [-afPpr] remote-path [local-path]
Retrieve the remote-path and store it on the local machine. If
the local path name is not specified, it is given the same name
it has on the remote machine. remote-path may contain glob(7)
characters and may match multiple files. If it does and
local-path is specified, then local-path must specify a
directory.
If the -a flag is specified, then attempt to resume partial
transfers of existing files. Note that resumption assumes that
any partial copy of the local file matches the remote copy. If
the remote file contents differ from the partial local copy then
the resultant file is likely to be corrupt.
If the -f flag is specified, then fsync(2) will be called after
the file transfer has completed to flush the file to disk.
If either the -P or -p flag is specified, then full file
permissions and access times are copied too.
If the -r flag is specified then directories will be copied
recursively. Note that sftp does not follow symbolic links when
performing recursive transfers.
help Display help text.
lcd [path]
Change local directory to path. If path is not specified, then
change directory to the local user's home directory.
lls [ls-options [path]]
Display local directory listing of either path or current
directory if path is not specified. ls-options may contain any
flags supported by the local system's ls(1) command. path may
contain glob(7) characters and may match multiple files.
lmkdir path
Create local directory specified by path.
ln [-s] oldpath newpath
Create a link from oldpath to newpath. If the -s flag is
specified the created link is a symbolic link, otherwise it is a
hard link.
lpwd Print local working directory.
ls [-1afhlnrSt] [path]
Display a remote directory listing of either path or the current
directory if path is not specified. path may contain glob(7)
characters and may match multiple files.
The following flags are recognized and alter the behaviour of ls
accordingly:
-1 Produce single columnar output.
-a List files beginning with a dot (M-bM-^@M-^X.M-bM-^@M-^Y).
-f Do not sort the listing. The default sort order is
lexicographical.
-h When used with a long format option, use unit suffixes:
Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte,
and Exabyte in order to reduce the number of digits to
four or fewer using powers of 2 for sizes (K=1024,
M=1048576, etc.).
-l Display additional details including permissions and
ownership information.
-n Produce a long listing with user and group information
presented numerically.
-r Reverse the sort order of the listing.
-S Sort the listing by file size.
-t Sort the listing by last modification time.
lumask umask
Set local umask to umask.
mkdir path
Create remote directory specified by path.
progress
Toggle display of progress meter.
put [-afPpr] local-path [remote-path]
Upload local-path and store it on the remote machine. If the
remote path name is not specified, it is given the same name it
has on the local machine. local-path may contain glob(7)
characters and may match multiple files. If it does and
remote-path is specified, then remote-path must specify a
directory.
If the -a flag is specified, then attempt to resume partial
transfers of existing files. Note that resumption assumes that
any partial copy of the remote file matches the local copy. If
the local file contents differ from the remote local copy then
the resultant file is likely to be corrupt.
If the -f flag is specified, then a request will be sent to the
server to call fsync(2) after the file has been transferred.
Note that this is only supported by servers that implement the
"fsync@openssh.com" extension.
If either the -P or -p flag is specified, then full file
permissions and access times are copied too.
If the -r flag is specified then directories will be copied
recursively. Note that sftp does not follow symbolic links when
performing recursive transfers.
pwd Display remote working directory.
quit Quit sftp.
reget [-Ppr] remote-path [local-path]
Resume download of remote-path. Equivalent to get with the -a
flag set.
reput [-Ppr] [local-path] remote-path
Resume upload of [local-path]. Equivalent to put with the -a
flag set.
rename oldpath newpath
Rename remote file from oldpath to newpath.
rm path
Delete remote file specified by path.
rmdir path
Remove remote directory specified by path.
symlink oldpath newpath
Create a symbolic link from oldpath to newpath.
version
Display the sftp protocol version.
!command
Execute command in local shell.
! Escape to local shell.
? Synonym for help.
SEE ALSO
ftp(1), ls(1), scp(1), ssh(1), ssh-add(1), ssh-keygen(1), ssh_config(5),
glob(7), sftp-server(8), sshd(8)
T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh-
filexfer-00.txt, January 2001, work in progress material.
-OpenBSD 6.4 September 20, 2018 OpenBSD 6.4
+OpenBSD 6.5 January 22, 2019 OpenBSD 6.5
diff --git a/sftp.1 b/sftp.1
index 0fd54cae090e..259095885a78 100644
--- a/sftp.1
+++ b/sftp.1
@@ -1,631 +1,673 @@
-.\" $OpenBSD: sftp.1,v 1.120 2018/09/20 06:58:48 jmc Exp $
+.\" $OpenBSD: sftp.1,v 1.125 2019/01/22 06:58:31 jmc Exp $
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: September 20 2018 $
+.Dd $Mdocdate: January 22 2019 $
.Dt SFTP 1
.Os
.Sh NAME
.Nm sftp
.Nd secure file transfer program
.Sh SYNOPSIS
.Nm sftp
.Op Fl 46aCfpqrv
.Op Fl B Ar buffer_size
.Op Fl b Ar batchfile
.Op Fl c Ar cipher
.Op Fl D Ar sftp_server_path
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
+.Op Fl J Ar destination
.Op Fl l Ar limit
.Op Fl o Ar ssh_option
.Op Fl P Ar port
.Op Fl R Ar num_requests
.Op Fl S Ar program
.Op Fl s Ar subsystem | sftp_server
.Ar destination
.Sh DESCRIPTION
.Nm
is a file transfer program, similar to
.Xr ftp 1 ,
which performs all operations over an encrypted
.Xr ssh 1
transport.
It may also use many features of ssh, such as public key authentication and
compression.
.Pp
The
.Ar destination
may be specified either as
.Sm off
.Oo user @ Oc host Op : path
.Sm on
or as a URI in the form
.Sm off
.No sftp:// Oo user @ Oc host Oo : port Oc Op / path .
.Sm on
.Pp
If the
.Ar destination
includes a
.Ar path
and it is not a directory,
.Nm
will retrieve files automatically if a non-interactive
authentication method is used; otherwise it will do so after
successful interactive authentication.
.Pp
If no
.Ar path
is specified, or if the
.Ar path
is a directory,
.Nm
will log in to the specified
.Ar host
and enter interactive command mode, changing to the remote directory
if one was specified.
An optional trailing slash can be used to force the
.Ar path
to be interpreted as a directory.
.Pp
Since the destination formats use colon characters to delimit host
names from path names or port numbers, IPv6 addresses must be
enclosed in square brackets to avoid ambiguity.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl 4
Forces
.Nm
to use IPv4 addresses only.
.It Fl 6
Forces
.Nm
to use IPv6 addresses only.
.It Fl a
Attempt to continue interrupted transfers rather than overwriting
existing partial or complete copies of files.
If the partial contents differ from those being transferred,
then the resultant file is likely to be corrupt.
.It Fl B Ar buffer_size
Specify the size of the buffer that
.Nm
uses when transferring files.
Larger buffers require fewer round trips at the cost of higher
memory consumption.
The default is 32768 bytes.
.It Fl b Ar batchfile
Batch mode reads a series of commands from an input
.Ar batchfile
instead of
.Em stdin .
Since it lacks user interaction it should be used in conjunction with
non-interactive authentication to obviate the need to enter a password
at connection time (see
.Xr sshd 8
and
.Xr ssh-keygen 1
for details).
+.Pp
A
.Ar batchfile
of
.Sq \-
may be used to indicate standard input.
.Nm
will abort if any of the following
commands fail:
-.Ic get , put , reget , reput, rename , ln ,
+.Ic get , put , reget , reput , rename , ln ,
.Ic rm , mkdir , chdir , ls ,
.Ic lchdir , chmod , chown ,
.Ic chgrp , lpwd , df , symlink ,
and
.Ic lmkdir .
+.Pp
Termination on error can be suppressed on a command by command basis by
prefixing the command with a
.Sq \-
character (for example,
.Ic -rm /tmp/blah* ) .
+Echo of the command may be suppressed by prefixing the command with a
+.Sq @
+character.
+These two prefixes may be combined in any order, for example
+.Ic -@ls /bsd .
.It Fl C
Enables compression (via ssh's
.Fl C
flag).
.It Fl c Ar cipher
Selects the cipher to use for encrypting the data transfers.
This option is directly passed to
.Xr ssh 1 .
.It Fl D Ar sftp_server_path
Connect directly to a local sftp server
(rather than via
.Xr ssh 1 ) .
This option may be useful in debugging the client and server.
.It Fl F Ar ssh_config
Specifies an alternative
per-user configuration file for
.Xr ssh 1 .
This option is directly passed to
.Xr ssh 1 .
.It Fl f
Requests that files be flushed to disk immediately after transfer.
When uploading files, this feature is only enabled if the server
implements the "fsync@openssh.com" extension.
.It Fl i Ar identity_file
Selects the file from which the identity (private key) for public key
authentication is read.
This option is directly passed to
.Xr ssh 1 .
+.It Fl J Ar destination
+Connect to the target host by first making an
+.Nm
+connection to the jump host described by
+.Ar destination
+and then establishing a TCP forwarding to the ultimate destination from
+there.
+Multiple jump hops may be specified separated by comma characters.
+This is a shortcut to specify a
+.Cm ProxyJump
+configuration directive.
+This option is directly passed to
+.Xr ssh 1 .
.It Fl l Ar limit
Limits the used bandwidth, specified in Kbit/s.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
in the format used in
.Xr ssh_config 5 .
This is useful for specifying options
for which there is no separate
.Nm sftp
command-line flag.
For example, to specify an alternate port use:
.Ic sftp -oPort=24 .
For full details of the options listed below, and their possible values, see
.Xr ssh_config 5 .
.Pp
.Bl -tag -width Ds -offset indent -compact
.It AddressFamily
.It BatchMode
.It BindAddress
.It BindInterface
.It CanonicalDomains
.It CanonicalizeFallbackLocal
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
.It CASignatureAlgorithms
.It CertificateFile
.It ChallengeResponseAuthentication
.It CheckHostIP
.It Ciphers
.It Compression
.It ConnectionAttempts
.It ConnectTimeout
.It ControlMaster
.It ControlPath
.It ControlPersist
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
.It HostbasedAuthentication
.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
.It HostName
.It IdentitiesOnly
.It IdentityAgent
.It IdentityFile
.It IPQoS
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
.It KexAlgorithms
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
.It NumberOfPasswordPrompts
.It PasswordAuthentication
.It PKCS11Provider
.It Port
.It PreferredAuthentications
.It ProxyCommand
.It ProxyJump
.It PubkeyAcceptedKeyTypes
.It PubkeyAuthentication
.It RekeyLimit
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
.It SetEnv
.It StrictHostKeyChecking
.It TCPKeepAlive
.It UpdateHostKeys
.It User
.It UserKnownHostsFile
.It VerifyHostKeyDNS
.El
.It Fl P Ar port
Specifies the port to connect to on the remote host.
.It Fl p
Preserves modification times, access times, and modes from the
original files transferred.
.It Fl q
Quiet mode: disables the progress meter as well as warning and
diagnostic messages from
.Xr ssh 1 .
.It Fl R Ar num_requests
Specify how many requests may be outstanding at any one time.
Increasing this may slightly improve file transfer speed
but will increase memory usage.
The default is 64 outstanding requests.
.It Fl r
Recursively copy entire directories when uploading and downloading.
Note that
.Nm
does not follow symbolic links encountered in the tree traversal.
.It Fl S Ar program
Name of the
.Ar program
to use for the encrypted connection.
The program must understand
.Xr ssh 1
options.
.It Fl s Ar subsystem | sftp_server
Specifies the SSH2 subsystem or the path for an sftp server
on the remote host.
A path is useful when the remote
.Xr sshd 8
does not have an sftp subsystem configured.
.It Fl v
Raise logging level.
This option is also passed to ssh.
.El
.Sh INTERACTIVE COMMANDS
Once in interactive mode,
.Nm
understands a set of commands similar to those of
.Xr ftp 1 .
Commands are case insensitive.
Pathnames that contain spaces must be enclosed in quotes.
Any special characters contained within pathnames that are recognized by
.Xr glob 3
must be escaped with backslashes
.Pq Sq \e .
.Bl -tag -width Ds
.It Ic bye
Quit
.Nm sftp .
.It Ic cd Op Ar path
Change remote directory to
.Ar path .
If
.Ar path
is not specified, then change directory to the one the session started in.
-.It Ic chgrp Ar grp Ar path
+.It Xo Ic chgrp
+.Op Fl h
+.Ar grp
+.Ar path
+.Xc
Change group of file
.Ar path
to
.Ar grp .
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
.Ar grp
must be a numeric GID.
-.It Ic chmod Ar mode Ar path
+.It Xo Ic chmod
+.Op Fl h
+.Ar mode
+.Ar path
+.Xc
Change permissions of file
.Ar path
to
.Ar mode .
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
-.It Ic chown Ar own Ar path
+.It Xo Ic chown
+.Op Fl h
+.Ar own
+.Ar path
+.Xc
Change owner of file
.Ar path
to
.Ar own .
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
.Ar own
must be a numeric UID.
.It Xo Ic df
.Op Fl hi
.Op Ar path
.Xc
Display usage information for the filesystem holding the current directory
(or
.Ar path
if specified).
If the
.Fl h
flag is specified, the capacity information will be displayed using
"human-readable" suffixes.
The
.Fl i
flag requests display of inode information in addition to capacity information.
This command is only supported on servers that implement the
.Dq statvfs@openssh.com
extension.
.It Ic exit
Quit
.Nm sftp .
.It Xo Ic get
.Op Fl afPpr
.Ar remote-path
.Op Ar local-path
.Xc
Retrieve the
.Ar remote-path
and store it on the local machine.
If the local
path name is not specified, it is given the same name it has on the
remote machine.
.Ar remote-path
may contain
.Xr glob 7
characters and may match multiple files.
If it does and
.Ar local-path
is specified, then
.Ar local-path
must specify a directory.
.Pp
If the
.Fl a
flag is specified, then attempt to resume partial transfers of existing files.
Note that resumption assumes that any partial copy of the local file matches
the remote copy.
If the remote file contents differ from the partial local copy then the
resultant file is likely to be corrupt.
.Pp
If the
.Fl f
flag is specified, then
.Xr fsync 2
will be called after the file transfer has completed to flush the file
to disk.
.Pp
If either the
.Fl P
or
.Fl p
flag is specified, then full file permissions and access times are
copied too.
.Pp
If the
.Fl r
flag is specified then directories will be copied recursively.
Note that
.Nm
does not follow symbolic links when performing recursive transfers.
.It Ic help
Display help text.
.It Ic lcd Op Ar path
Change local directory to
.Ar path .
If
.Ar path
is not specified, then change directory to the local user's home directory.
.It Ic lls Op Ar ls-options Op Ar path
Display local directory listing of either
.Ar path
or current directory if
.Ar path
is not specified.
.Ar ls-options
may contain any flags supported by the local system's
.Xr ls 1
command.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
.It Ic lmkdir Ar path
Create local directory specified by
.Ar path .
.It Xo Ic ln
.Op Fl s
.Ar oldpath
.Ar newpath
.Xc
Create a link from
.Ar oldpath
to
.Ar newpath .
If the
.Fl s
flag is specified the created link is a symbolic link, otherwise it is
a hard link.
.It Ic lpwd
Print local working directory.
.It Xo Ic ls
.Op Fl 1afhlnrSt
.Op Ar path
.Xc
Display a remote directory listing of either
.Ar path
or the current directory if
.Ar path
is not specified.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
.Pp
The following flags are recognized and alter the behaviour of
.Ic ls
accordingly:
.Bl -tag -width Ds
.It Fl 1
Produce single columnar output.
.It Fl a
List files beginning with a dot
.Pq Sq \&. .
.It Fl f
Do not sort the listing.
The default sort order is lexicographical.
.It Fl h
When used with a long format option, use unit suffixes: Byte, Kilobyte,
Megabyte, Gigabyte, Terabyte, Petabyte, and Exabyte in order to reduce
the number of digits to four or fewer using powers of 2 for sizes (K=1024,
M=1048576, etc.).
.It Fl l
Display additional details including permissions
and ownership information.
.It Fl n
Produce a long listing with user and group information presented
numerically.
.It Fl r
Reverse the sort order of the listing.
.It Fl S
Sort the listing by file size.
.It Fl t
Sort the listing by last modification time.
.El
.It Ic lumask Ar umask
Set local umask to
.Ar umask .
.It Ic mkdir Ar path
Create remote directory specified by
.Ar path .
.It Ic progress
Toggle display of progress meter.
.It Xo Ic put
.Op Fl afPpr
.Ar local-path
.Op Ar remote-path
.Xc
Upload
.Ar local-path
and store it on the remote machine.
If the remote path name is not specified, it is given the same name it has
on the local machine.
.Ar local-path
may contain
.Xr glob 7
characters and may match multiple files.
If it does and
.Ar remote-path
is specified, then
.Ar remote-path
must specify a directory.
.Pp
If the
.Fl a
flag is specified, then attempt to resume partial
transfers of existing files.
Note that resumption assumes that any partial copy of the remote file
matches the local copy.
If the local file contents differ from the remote local copy then
the resultant file is likely to be corrupt.
.Pp
If the
.Fl f
flag is specified, then a request will be sent to the server to call
.Xr fsync 2
after the file has been transferred.
Note that this is only supported by servers that implement
the "fsync@openssh.com" extension.
.Pp
If either the
.Fl P
or
.Fl p
flag is specified, then full file permissions and access times are
copied too.
.Pp
If the
.Fl r
flag is specified then directories will be copied recursively.
Note that
.Nm
does not follow symbolic links when performing recursive transfers.
.It Ic pwd
Display remote working directory.
.It Ic quit
Quit
.Nm sftp .
.It Xo Ic reget
.Op Fl Ppr
.Ar remote-path
.Op Ar local-path
.Xc
Resume download of
.Ar remote-path .
Equivalent to
.Ic get
with the
.Fl a
flag set.
.It Xo Ic reput
.Op Fl Ppr
.Op Ar local-path
.Ar remote-path
.Xc
Resume upload of
.Op Ar local-path .
Equivalent to
.Ic put
with the
.Fl a
flag set.
.It Ic rename Ar oldpath Ar newpath
Rename remote file from
.Ar oldpath
to
.Ar newpath .
.It Ic rm Ar path
Delete remote file specified by
.Ar path .
.It Ic rmdir Ar path
Remove remote directory specified by
.Ar path .
.It Ic symlink Ar oldpath Ar newpath
Create a symbolic link from
.Ar oldpath
to
.Ar newpath .
.It Ic version
Display the
.Nm
protocol version.
.It Ic \&! Ns Ar command
Execute
.Ar command
in local shell.
.It Ic \&!
Escape to local shell.
.It Ic \&?
Synonym for help.
.El
.Sh SEE ALSO
.Xr ftp 1 ,
.Xr ls 1 ,
.Xr scp 1 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh_config 5 ,
.Xr glob 7 ,
.Xr sftp-server 8 ,
.Xr sshd 8
.Rs
.%A T. Ylonen
.%A S. Lehtinen
.%T "SSH File Transfer Protocol"
.%N draft-ietf-secsh-filexfer-00.txt
.%D January 2001
.%O work in progress material
.Re
diff --git a/sftp.c b/sftp.c
index 7db86c2d3cf0..44aa19d96737 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,2567 +1,2601 @@
-/* $OpenBSD: sftp.c,v 1.186 2018/09/07 04:26:56 dtucker Exp $ */
+/* $OpenBSD: sftp.c,v 1.190 2019/01/21 22:50:42 tb Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
#ifdef HAVE_SYS_STATVFS_H
#include <sys/statvfs.h>
#endif
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#ifdef HAVE_LOCALE_H
# include <locale.h>
#endif
#ifdef USE_LIBEDIT
#include <histedit.h>
#else
typedef void EditLine;
#endif
#include <limits.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
#include "xmalloc.h"
#include "log.h"
#include "pathnames.h"
#include "misc.h"
#include "utf8.h"
#include "sftp.h"
#include "ssherr.h"
#include "sshbuf.h"
#include "sftp-common.h"
#include "sftp-client.h"
#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */
#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */
/* File to read commands from */
FILE* infile;
/* Are we in batchfile mode? */
int batchmode = 0;
/* PID of ssh transport process */
static volatile pid_t sshpid = -1;
/* Suppress diagnositic messages */
int quiet = 0;
/* This is set to 0 if the progressmeter is not desired. */
int showprogress = 1;
/* When this option is set, we always recursively download/upload directories */
int global_rflag = 0;
/* When this option is set, we resume download or upload if possible */
int global_aflag = 0;
/* When this option is set, the file transfers will always preserve times */
int global_pflag = 0;
/* When this option is set, transfers will have fsync() called on each file */
int global_fflag = 0;
/* SIGINT received during command processing */
volatile sig_atomic_t interrupted = 0;
/* I wish qsort() took a separate ctx for the comparison function...*/
int sort_flag;
glob_t *sort_glob;
/* Context used for commandline completion */
struct complete_ctx {
struct sftp_conn *conn;
char **remote_pathp;
};
int remote_glob(struct sftp_conn *, const char *, int,
int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
extern char *__progname;
/* Separators for interactive commands */
#define WHITESPACE " \t\r\n"
/* ls flags */
#define LS_LONG_VIEW 0x0001 /* Full view ala ls -l */
#define LS_SHORT_VIEW 0x0002 /* Single row view ala ls -1 */
#define LS_NUMERIC_VIEW 0x0004 /* Long view with numeric uid/gid */
#define LS_NAME_SORT 0x0008 /* Sort by name (default) */
#define LS_TIME_SORT 0x0010 /* Sort by mtime */
#define LS_SIZE_SORT 0x0020 /* Sort by file size */
#define LS_REVERSE_SORT 0x0040 /* Reverse sort order */
#define LS_SHOW_ALL 0x0080 /* Don't skip filenames starting with '.' */
#define LS_SI_UNITS 0x0100 /* Display sizes as K, M, G, etc. */
#define VIEW_FLAGS (LS_LONG_VIEW|LS_SHORT_VIEW|LS_NUMERIC_VIEW|LS_SI_UNITS)
#define SORT_FLAGS (LS_NAME_SORT|LS_TIME_SORT|LS_SIZE_SORT)
/* Commands for interactive mode */
enum sftp_command {
I_CHDIR = 1,
I_CHGRP,
I_CHMOD,
I_CHOWN,
I_DF,
I_GET,
I_HELP,
I_LCHDIR,
I_LINK,
I_LLS,
I_LMKDIR,
I_LPWD,
I_LS,
I_LUMASK,
I_MKDIR,
I_PUT,
I_PWD,
I_QUIT,
I_REGET,
I_RENAME,
I_REPUT,
I_RM,
I_RMDIR,
I_SHELL,
I_SYMLINK,
I_VERSION,
I_PROGRESS,
};
struct CMD {
const char *c;
const int n;
const int t;
};
/* Type of completion */
#define NOARGS 0
#define REMOTE 1
#define LOCAL 2
static const struct CMD cmds[] = {
{ "bye", I_QUIT, NOARGS },
{ "cd", I_CHDIR, REMOTE },
{ "chdir", I_CHDIR, REMOTE },
{ "chgrp", I_CHGRP, REMOTE },
{ "chmod", I_CHMOD, REMOTE },
{ "chown", I_CHOWN, REMOTE },
{ "df", I_DF, REMOTE },
{ "dir", I_LS, REMOTE },
{ "exit", I_QUIT, NOARGS },
{ "get", I_GET, REMOTE },
{ "help", I_HELP, NOARGS },
{ "lcd", I_LCHDIR, LOCAL },
{ "lchdir", I_LCHDIR, LOCAL },
{ "lls", I_LLS, LOCAL },
{ "lmkdir", I_LMKDIR, LOCAL },
{ "ln", I_LINK, REMOTE },
{ "lpwd", I_LPWD, LOCAL },
{ "ls", I_LS, REMOTE },
{ "lumask", I_LUMASK, NOARGS },
{ "mkdir", I_MKDIR, REMOTE },
{ "mget", I_GET, REMOTE },
{ "mput", I_PUT, LOCAL },
{ "progress", I_PROGRESS, NOARGS },
{ "put", I_PUT, LOCAL },
{ "pwd", I_PWD, REMOTE },
{ "quit", I_QUIT, NOARGS },
{ "reget", I_REGET, REMOTE },
{ "rename", I_RENAME, REMOTE },
{ "reput", I_REPUT, LOCAL },
{ "rm", I_RM, REMOTE },
{ "rmdir", I_RMDIR, REMOTE },
{ "symlink", I_SYMLINK, REMOTE },
{ "version", I_VERSION, NOARGS },
{ "!", I_SHELL, NOARGS },
{ "?", I_HELP, NOARGS },
{ NULL, -1, -1 }
};
/* ARGSUSED */
static void
killchild(int signo)
{
if (sshpid > 1) {
kill(sshpid, SIGTERM);
waitpid(sshpid, NULL, 0);
}
_exit(1);
}
/* ARGSUSED */
static void
suspchild(int signo)
{
if (sshpid > 1) {
kill(sshpid, signo);
while (waitpid(sshpid, NULL, WUNTRACED) == -1 && errno == EINTR)
continue;
}
kill(getpid(), SIGSTOP);
}
/* ARGSUSED */
static void
cmd_interrupt(int signo)
{
const char msg[] = "\rInterrupt \n";
int olderrno = errno;
(void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
interrupted = 1;
errno = olderrno;
}
/*ARGSUSED*/
static void
sigchld_handler(int sig)
{
int save_errno = errno;
pid_t pid;
const char msg[] = "\rConnection closed. \n";
/* Report if ssh transport process dies. */
while ((pid = waitpid(sshpid, NULL, WNOHANG)) == -1 && errno == EINTR)
continue;
if (pid == sshpid) {
(void)write(STDERR_FILENO, msg, sizeof(msg) - 1);
sshpid = -1;
}
errno = save_errno;
}
static void
help(void)
{
printf("Available commands:\n"
"bye Quit sftp\n"
"cd path Change remote directory to 'path'\n"
- "chgrp grp path Change group of file 'path' to 'grp'\n"
- "chmod mode path Change permissions of file 'path' to 'mode'\n"
- "chown own path Change owner of file 'path' to 'own'\n"
+ "chgrp [-h] grp path Change group of file 'path' to 'grp'\n"
+ "chmod [-h] mode path Change permissions of file 'path' to 'mode'\n"
+ "chown [-h] own path Change owner of file 'path' to 'own'\n"
"df [-hi] [path] Display statistics for current directory or\n"
" filesystem containing 'path'\n"
"exit Quit sftp\n"
"get [-afPpRr] remote [local] Download file\n"
"reget [-fPpRr] remote [local] Resume download file\n"
"reput [-fPpRr] [local] remote Resume upload file\n"
"help Display this help text\n"
"lcd path Change local directory to 'path'\n"
"lls [ls-options [path]] Display local directory listing\n"
"lmkdir path Create local directory\n"
"ln [-s] oldpath newpath Link remote file (-s for symlink)\n"
"lpwd Print local working directory\n"
"ls [-1afhlnrSt] [path] Display remote directory listing\n"
"lumask umask Set local umask to 'umask'\n"
"mkdir path Create remote directory\n"
"progress Toggle display of progress meter\n"
"put [-afPpRr] local [remote] Upload file\n"
"pwd Display remote working directory\n"
"quit Quit sftp\n"
"rename oldpath newpath Rename remote file\n"
"rm path Delete remote file\n"
"rmdir path Remove remote directory\n"
"symlink oldpath newpath Symlink remote file\n"
"version Show SFTP version\n"
"!command Execute 'command' in local shell\n"
"! Escape to local shell\n"
"? Synonym for help\n");
}
static void
local_do_shell(const char *args)
{
int status;
char *shell;
pid_t pid;
if (!*args)
args = NULL;
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
if ((pid = fork()) == -1)
fatal("Couldn't fork: %s", strerror(errno));
if (pid == 0) {
/* XXX: child has pipe fds to ssh subproc open - issue? */
if (args) {
debug3("Executing %s -c \"%s\"", shell, args);
execl(shell, shell, "-c", args, (char *)NULL);
} else {
debug3("Executing %s", shell);
execl(shell, shell, (char *)NULL);
}
fprintf(stderr, "Couldn't execute \"%s\": %s\n", shell,
strerror(errno));
_exit(1);
}
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for child: %s", strerror(errno));
if (!WIFEXITED(status))
error("Shell exited abnormally");
else if (WEXITSTATUS(status))
error("Shell exited with status %d", WEXITSTATUS(status));
}
static void
local_do_ls(const char *args)
{
if (!args || !*args)
local_do_shell(_PATH_LS);
else {
int len = strlen(_PATH_LS " ") + strlen(args) + 1;
char *buf = xmalloc(len);
/* XXX: quoting - rip quoting code from ftp? */
snprintf(buf, len, _PATH_LS " %s", args);
local_do_shell(buf);
free(buf);
}
}
/* Strip one path (usually the pwd) from the start of another */
static char *
path_strip(const char *path, const char *strip)
{
size_t len;
if (strip == NULL)
return (xstrdup(path));
len = strlen(strip);
if (strncmp(path, strip, len) == 0) {
if (strip[len - 1] != '/' && path[len] == '/')
len++;
return (xstrdup(path + len));
}
return (xstrdup(path));
}
static char *
make_absolute(char *p, const char *pwd)
{
char *abs_str;
/* Derelativise */
- if (p && p[0] != '/') {
+ if (p && !path_absolute(p)) {
abs_str = path_append(pwd, p);
free(p);
return(abs_str);
} else
return(p);
}
static int
parse_getput_flags(const char *cmd, char **argv, int argc,
int *aflag, int *fflag, int *pflag, int *rflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
*aflag = *fflag = *rflag = *pflag = 0;
while ((ch = getopt(argc, argv, "afPpRr")) != -1) {
switch (ch) {
case 'a':
*aflag = 1;
break;
case 'f':
*fflag = 1;
break;
case 'p':
case 'P':
*pflag = 1;
break;
case 'r':
case 'R':
*rflag = 1;
break;
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
}
}
return optind;
}
static int
parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
*sflag = 0;
while ((ch = getopt(argc, argv, "s")) != -1) {
switch (ch) {
case 's':
*sflag = 1;
break;
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
}
}
return optind;
}
static int
parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
*lflag = 0;
while ((ch = getopt(argc, argv, "l")) != -1) {
switch (ch) {
case 'l':
*lflag = 1;
break;
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
}
}
return optind;
}
static int
parse_ls_flags(char **argv, int argc, int *lflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
*lflag = LS_NAME_SORT;
while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) {
switch (ch) {
case '1':
*lflag &= ~VIEW_FLAGS;
*lflag |= LS_SHORT_VIEW;
break;
case 'S':
*lflag &= ~SORT_FLAGS;
*lflag |= LS_SIZE_SORT;
break;
case 'a':
*lflag |= LS_SHOW_ALL;
break;
case 'f':
*lflag &= ~SORT_FLAGS;
break;
case 'h':
*lflag |= LS_SI_UNITS;
break;
case 'l':
*lflag &= ~LS_SHORT_VIEW;
*lflag |= LS_LONG_VIEW;
break;
case 'n':
*lflag &= ~LS_SHORT_VIEW;
*lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
break;
case 'r':
*lflag |= LS_REVERSE_SORT;
break;
case 't':
*lflag &= ~SORT_FLAGS;
*lflag |= LS_TIME_SORT;
break;
default:
error("ls: Invalid flag -%c", optopt);
return -1;
}
}
return optind;
}
static int
parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
*hflag = *iflag = 0;
while ((ch = getopt(argc, argv, "hi")) != -1) {
switch (ch) {
case 'h':
*hflag = 1;
break;
case 'i':
*iflag = 1;
break;
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
}
}
return optind;
}
+static int
+parse_ch_flags(const char *cmd, char **argv, int argc, int *hflag)
+{
+ extern int opterr, optind, optopt, optreset;
+ int ch;
+
+ optind = optreset = 1;
+ opterr = 0;
+
+ *hflag = 0;
+ while ((ch = getopt(argc, argv, "h")) != -1) {
+ switch (ch) {
+ case 'h':
+ *hflag = 1;
+ break;
+ default:
+ error("%s: Invalid flag -%c", cmd, optopt);
+ return -1;
+ }
+ }
+
+ return optind;
+}
+
static int
parse_no_flags(const char *cmd, char **argv, int argc)
{
extern int opterr, optind, optopt, optreset;
int ch;
optind = optreset = 1;
opterr = 0;
while ((ch = getopt(argc, argv, "")) != -1) {
switch (ch) {
default:
error("%s: Invalid flag -%c", cmd, optopt);
return -1;
}
}
return optind;
}
static int
is_dir(const char *path)
{
struct stat sb;
/* XXX: report errors? */
if (stat(path, &sb) == -1)
return(0);
return(S_ISDIR(sb.st_mode));
}
static int
remote_is_dir(struct sftp_conn *conn, const char *path)
{
Attrib *a;
/* XXX: report errors? */
if ((a = do_stat(conn, path, 1)) == NULL)
return(0);
if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
return(0);
return(S_ISDIR(a->perm));
}
/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
static int
pathname_is_dir(const char *pathname)
{
size_t l = strlen(pathname);
return l > 0 && pathname[l - 1] == '/';
}
static int
process_get(struct sftp_conn *conn, const char *src, const char *dst,
const char *pwd, int pflag, int rflag, int resume, int fflag)
{
char *abs_src = NULL;
char *abs_dst = NULL;
glob_t g;
char *filename, *tmp=NULL;
int i, r, err = 0;
abs_src = xstrdup(src);
abs_src = make_absolute(abs_src, pwd);
memset(&g, 0, sizeof(g));
debug3("Looking up %s", abs_src);
if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
if (r == GLOB_NOSPACE) {
error("Too many matches for \"%s\".", abs_src);
} else {
error("File \"%s\" not found.", abs_src);
}
err = -1;
goto out;
}
/*
* If multiple matches then dst must be a directory or
* unspecified.
*/
if (g.gl_matchc > 1 && dst != NULL && !is_dir(dst)) {
error("Multiple source paths, but destination "
"\"%s\" is not a directory", dst);
err = -1;
goto out;
}
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
tmp = xstrdup(g.gl_pathv[i]);
if ((filename = basename(tmp)) == NULL) {
error("basename %s: %s", tmp, strerror(errno));
free(tmp);
err = -1;
goto out;
}
if (g.gl_matchc == 1 && dst) {
if (is_dir(dst)) {
abs_dst = path_append(dst, filename);
} else {
abs_dst = xstrdup(dst);
}
} else if (dst) {
abs_dst = path_append(dst, filename);
} else {
abs_dst = xstrdup(filename);
}
free(tmp);
resume |= global_aflag;
if (!quiet && resume)
mprintf("Resuming %s to %s\n",
g.gl_pathv[i], abs_dst);
else if (!quiet && !resume)
mprintf("Fetching %s to %s\n",
g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
pflag || global_pflag, 1, resume,
fflag || global_fflag) == -1)
err = -1;
} else {
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
pflag || global_pflag, resume,
fflag || global_fflag) == -1)
err = -1;
}
free(abs_dst);
abs_dst = NULL;
}
out:
free(abs_src);
globfree(&g);
return(err);
}
static int
process_put(struct sftp_conn *conn, const char *src, const char *dst,
const char *pwd, int pflag, int rflag, int resume, int fflag)
{
char *tmp_dst = NULL;
char *abs_dst = NULL;
char *tmp = NULL, *filename = NULL;
glob_t g;
int err = 0;
int i, dst_is_dir = 1;
struct stat sb;
if (dst) {
tmp_dst = xstrdup(dst);
tmp_dst = make_absolute(tmp_dst, pwd);
}
memset(&g, 0, sizeof(g));
debug3("Looking up %s", src);
if (glob(src, GLOB_NOCHECK | GLOB_MARK, NULL, &g)) {
error("File \"%s\" not found.", src);
err = -1;
goto out;
}
/* If we aren't fetching to pwd then stash this status for later */
if (tmp_dst != NULL)
dst_is_dir = remote_is_dir(conn, tmp_dst);
/* If multiple matches, dst may be directory or unspecified */
if (g.gl_matchc > 1 && tmp_dst && !dst_is_dir) {
error("Multiple paths match, but destination "
"\"%s\" is not a directory", tmp_dst);
err = -1;
goto out;
}
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
if (stat(g.gl_pathv[i], &sb) == -1) {
err = -1;
error("stat %s: %s", g.gl_pathv[i], strerror(errno));
continue;
}
tmp = xstrdup(g.gl_pathv[i]);
if ((filename = basename(tmp)) == NULL) {
error("basename %s: %s", tmp, strerror(errno));
free(tmp);
err = -1;
goto out;
}
if (g.gl_matchc == 1 && tmp_dst) {
/* If directory specified, append filename */
if (dst_is_dir)
abs_dst = path_append(tmp_dst, filename);
else
abs_dst = xstrdup(tmp_dst);
} else if (tmp_dst) {
abs_dst = path_append(tmp_dst, filename);
} else {
abs_dst = make_absolute(xstrdup(filename), pwd);
}
free(tmp);
resume |= global_aflag;
if (!quiet && resume)
mprintf("Resuming upload of %s to %s\n",
g.gl_pathv[i], abs_dst);
else if (!quiet && !resume)
mprintf("Uploading %s to %s\n",
g.gl_pathv[i], abs_dst);
if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume,
fflag || global_fflag) == -1)
err = -1;
} else {
if (do_upload(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, resume,
fflag || global_fflag) == -1)
err = -1;
}
}
out:
free(abs_dst);
free(tmp_dst);
globfree(&g);
return(err);
}
static int
sdirent_comp(const void *aa, const void *bb)
{
SFTP_DIRENT *a = *(SFTP_DIRENT **)aa;
SFTP_DIRENT *b = *(SFTP_DIRENT **)bb;
int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
if (sort_flag & LS_NAME_SORT)
return (rmul * strcmp(a->filename, b->filename));
else if (sort_flag & LS_TIME_SORT)
return (rmul * NCMP(a->a.mtime, b->a.mtime));
else if (sort_flag & LS_SIZE_SORT)
return (rmul * NCMP(a->a.size, b->a.size));
fatal("Unknown ls sort type");
}
/* sftp ls.1 replacement for directories */
static int
do_ls_dir(struct sftp_conn *conn, const char *path,
const char *strip_path, int lflag)
{
int n;
u_int c = 1, colspace = 0, columns = 1;
SFTP_DIRENT **d;
if ((n = do_readdir(conn, path, &d)) != 0)
return (n);
if (!(lflag & LS_SHORT_VIEW)) {
u_int m = 0, width = 80;
struct winsize ws;
char *tmp;
/* Count entries for sort and find longest filename */
for (n = 0; d[n] != NULL; n++) {
if (d[n]->filename[0] != '.' || (lflag & LS_SHOW_ALL))
m = MAXIMUM(m, strlen(d[n]->filename));
}
/* Add any subpath that also needs to be counted */
tmp = path_strip(path, strip_path);
m += strlen(tmp);
free(tmp);
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col;
columns = width / (m + 2);
columns = MAXIMUM(columns, 1);
colspace = width / columns;
colspace = MINIMUM(colspace, width);
}
if (lflag & SORT_FLAGS) {
for (n = 0; d[n] != NULL; n++)
; /* count entries */
sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
qsort(d, n, sizeof(*d), sdirent_comp);
}
for (n = 0; d[n] != NULL && !interrupted; n++) {
char *tmp, *fname;
if (d[n]->filename[0] == '.' && !(lflag & LS_SHOW_ALL))
continue;
tmp = path_append(path, d[n]->filename);
fname = path_strip(tmp, strip_path);
free(tmp);
if (lflag & LS_LONG_VIEW) {
if (lflag & (LS_NUMERIC_VIEW|LS_SI_UNITS)) {
char *lname;
struct stat sb;
memset(&sb, 0, sizeof(sb));
attrib_to_stat(&d[n]->a, &sb);
lname = ls_file(fname, &sb, 1,
(lflag & LS_SI_UNITS));
mprintf("%s\n", lname);
free(lname);
} else
mprintf("%s\n", d[n]->longname);
} else {
mprintf("%-*s", colspace, fname);
if (c >= columns) {
printf("\n");
c = 1;
} else
c++;
}
free(fname);
}
if (!(lflag & LS_LONG_VIEW) && (c != 1))
printf("\n");
free_sftp_dirents(d);
return (0);
}
static int
sglob_comp(const void *aa, const void *bb)
{
u_int a = *(const u_int *)aa;
u_int b = *(const u_int *)bb;
const char *ap = sort_glob->gl_pathv[a];
const char *bp = sort_glob->gl_pathv[b];
const struct stat *as = sort_glob->gl_statv[a];
const struct stat *bs = sort_glob->gl_statv[b];
int rmul = sort_flag & LS_REVERSE_SORT ? -1 : 1;
#define NCMP(a,b) (a == b ? 0 : (a < b ? 1 : -1))
if (sort_flag & LS_NAME_SORT)
return (rmul * strcmp(ap, bp));
else if (sort_flag & LS_TIME_SORT) {
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
#elif defined(HAVE_STRUCT_STAT_ST_MTIME)
return (rmul * NCMP(as->st_mtime, bs->st_mtime));
#else
return rmul * 1;
#endif
} else if (sort_flag & LS_SIZE_SORT)
return (rmul * NCMP(as->st_size, bs->st_size));
fatal("Unknown ls sort type");
}
/* sftp ls.1 replacement which handles path globs */
static int
do_globbed_ls(struct sftp_conn *conn, const char *path,
const char *strip_path, int lflag)
{
char *fname, *lname;
glob_t g;
int err, r;
struct winsize ws;
u_int i, j, nentries, *indices = NULL, c = 1;
u_int colspace = 0, columns = 1, m = 0, width = 80;
memset(&g, 0, sizeof(g));
if ((r = remote_glob(conn, path,
GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT,
NULL, &g)) != 0 ||
(g.gl_pathc && !g.gl_matchc)) {
if (g.gl_pathc)
globfree(&g);
if (r == GLOB_NOSPACE) {
error("Can't ls: Too many matches for \"%s\"", path);
} else {
error("Can't ls: \"%s\" not found", path);
}
return -1;
}
if (interrupted)
goto out;
/*
* If the glob returns a single match and it is a directory,
* then just list its contents.
*/
if (g.gl_matchc == 1 && g.gl_statv[0] != NULL &&
S_ISDIR(g.gl_statv[0]->st_mode)) {
err = do_ls_dir(conn, g.gl_pathv[0], strip_path, lflag);
globfree(&g);
return err;
}
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col;
if (!(lflag & LS_SHORT_VIEW)) {
/* Count entries for sort and find longest filename */
for (i = 0; g.gl_pathv[i]; i++)
m = MAXIMUM(m, strlen(g.gl_pathv[i]));
columns = width / (m + 2);
columns = MAXIMUM(columns, 1);
colspace = width / columns;
}
/*
* Sorting: rather than mess with the contents of glob_t, prepare
* an array of indices into it and sort that. For the usual
* unsorted case, the indices are just the identity 1=1, 2=2, etc.
*/
for (nentries = 0; g.gl_pathv[nentries] != NULL; nentries++)
; /* count entries */
indices = calloc(nentries, sizeof(*indices));
for (i = 0; i < nentries; i++)
indices[i] = i;
if (lflag & SORT_FLAGS) {
sort_glob = &g;
sort_flag = lflag & (SORT_FLAGS|LS_REVERSE_SORT);
qsort(indices, nentries, sizeof(*indices), sglob_comp);
sort_glob = NULL;
}
for (j = 0; j < nentries && !interrupted; j++) {
i = indices[j];
fname = path_strip(g.gl_pathv[i], strip_path);
if (lflag & LS_LONG_VIEW) {
if (g.gl_statv[i] == NULL) {
error("no stat information for %s", fname);
continue;
}
lname = ls_file(fname, g.gl_statv[i], 1,
(lflag & LS_SI_UNITS));
mprintf("%s\n", lname);
free(lname);
} else {
mprintf("%-*s", colspace, fname);
if (c >= columns) {
printf("\n");
c = 1;
} else
c++;
}
free(fname);
}
if (!(lflag & LS_LONG_VIEW) && (c != 1))
printf("\n");
out:
if (g.gl_pathc)
globfree(&g);
free(indices);
return 0;
}
static int
do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag)
{
struct sftp_statvfs st;
char s_used[FMT_SCALED_STRSIZE], s_avail[FMT_SCALED_STRSIZE];
char s_root[FMT_SCALED_STRSIZE], s_total[FMT_SCALED_STRSIZE];
char s_icapacity[16], s_dcapacity[16];
if (do_statvfs(conn, path, &st, 1) == -1)
return -1;
if (st.f_files == 0)
strlcpy(s_icapacity, "ERR", sizeof(s_icapacity));
else {
snprintf(s_icapacity, sizeof(s_icapacity), "%3llu%%",
(unsigned long long)(100 * (st.f_files - st.f_ffree) /
st.f_files));
}
if (st.f_blocks == 0)
strlcpy(s_dcapacity, "ERR", sizeof(s_dcapacity));
else {
snprintf(s_dcapacity, sizeof(s_dcapacity), "%3llu%%",
(unsigned long long)(100 * (st.f_blocks - st.f_bfree) /
st.f_blocks));
}
if (iflag) {
printf(" Inodes Used Avail "
"(root) %%Capacity\n");
printf("%11llu %11llu %11llu %11llu %s\n",
(unsigned long long)st.f_files,
(unsigned long long)(st.f_files - st.f_ffree),
(unsigned long long)st.f_favail,
(unsigned long long)st.f_ffree, s_icapacity);
} else if (hflag) {
strlcpy(s_used, "error", sizeof(s_used));
strlcpy(s_avail, "error", sizeof(s_avail));
strlcpy(s_root, "error", sizeof(s_root));
strlcpy(s_total, "error", sizeof(s_total));
fmt_scaled((st.f_blocks - st.f_bfree) * st.f_frsize, s_used);
fmt_scaled(st.f_bavail * st.f_frsize, s_avail);
fmt_scaled(st.f_bfree * st.f_frsize, s_root);
fmt_scaled(st.f_blocks * st.f_frsize, s_total);
printf(" Size Used Avail (root) %%Capacity\n");
printf("%7sB %7sB %7sB %7sB %s\n",
s_total, s_used, s_avail, s_root, s_dcapacity);
} else {
printf(" Size Used Avail "
"(root) %%Capacity\n");
printf("%12llu %12llu %12llu %12llu %s\n",
(unsigned long long)(st.f_frsize * st.f_blocks / 1024),
(unsigned long long)(st.f_frsize *
(st.f_blocks - st.f_bfree) / 1024),
(unsigned long long)(st.f_frsize * st.f_bavail / 1024),
(unsigned long long)(st.f_frsize * st.f_bfree / 1024),
s_dcapacity);
}
return 0;
}
/*
* Undo escaping of glob sequences in place. Used to undo extra escaping
* applied in makeargv() when the string is destined for a function that
* does not glob it.
*/
static void
undo_glob_escape(char *s)
{
size_t i, j;
for (i = j = 0;;) {
if (s[i] == '\0') {
s[j] = '\0';
return;
}
if (s[i] != '\\') {
s[j++] = s[i++];
continue;
}
/* s[i] == '\\' */
++i;
switch (s[i]) {
case '?':
case '[':
case '*':
case '\\':
s[j++] = s[i++];
break;
case '\0':
s[j++] = '\\';
s[j] = '\0';
return;
default:
s[j++] = '\\';
s[j++] = s[i++];
break;
}
}
}
/*
* Split a string into an argument vector using sh(1)-style quoting,
* comment and escaping rules, but with some tweaks to handle glob(3)
* wildcards.
* The "sloppy" flag allows for recovery from missing terminating quote, for
* use in parsing incomplete commandlines during tab autocompletion.
*
* Returns NULL on error or a NULL-terminated array of arguments.
*
* If "lastquote" is not NULL, the quoting character used for the last
* argument is placed in *lastquote ("\0", "'" or "\"").
*
* If "terminated" is not NULL, *terminated will be set to 1 when the
* last argument's quote has been properly terminated or 0 otherwise.
* This parameter is only of use if "sloppy" is set.
*/
#define MAXARGS 128
#define MAXARGLEN 8192
static char **
makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
u_int *terminated)
{
int argc, quot;
size_t i, j;
static char argvs[MAXARGLEN];
static char *argv[MAXARGS + 1];
enum { MA_START, MA_SQUOTE, MA_DQUOTE, MA_UNQUOTED } state, q;
*argcp = argc = 0;
if (strlen(arg) > sizeof(argvs) - 1) {
args_too_longs:
error("string too long");
return NULL;
}
if (terminated != NULL)
*terminated = 1;
if (lastquote != NULL)
*lastquote = '\0';
state = MA_START;
i = j = 0;
for (;;) {
if ((size_t)argc >= sizeof(argv) / sizeof(*argv)){
error("Too many arguments.");
return NULL;
}
if (isspace((unsigned char)arg[i])) {
if (state == MA_UNQUOTED) {
/* Terminate current argument */
argvs[j++] = '\0';
argc++;
state = MA_START;
} else if (state != MA_START)
argvs[j++] = arg[i];
} else if (arg[i] == '"' || arg[i] == '\'') {
q = arg[i] == '"' ? MA_DQUOTE : MA_SQUOTE;
if (state == MA_START) {
argv[argc] = argvs + j;
state = q;
if (lastquote != NULL)
*lastquote = arg[i];
} else if (state == MA_UNQUOTED)
state = q;
else if (state == q)
state = MA_UNQUOTED;
else
argvs[j++] = arg[i];
} else if (arg[i] == '\\') {
if (state == MA_SQUOTE || state == MA_DQUOTE) {
quot = state == MA_SQUOTE ? '\'' : '"';
/* Unescape quote we are in */
/* XXX support \n and friends? */
if (arg[i + 1] == quot) {
i++;
argvs[j++] = arg[i];
} else if (arg[i + 1] == '?' ||
arg[i + 1] == '[' || arg[i + 1] == '*') {
/*
* Special case for sftp: append
* double-escaped glob sequence -
* glob will undo one level of
* escaping. NB. string can grow here.
*/
if (j >= sizeof(argvs) - 5)
goto args_too_longs;
argvs[j++] = '\\';
argvs[j++] = arg[i++];
argvs[j++] = '\\';
argvs[j++] = arg[i];
} else {
argvs[j++] = arg[i++];
argvs[j++] = arg[i];
}
} else {
if (state == MA_START) {
argv[argc] = argvs + j;
state = MA_UNQUOTED;
if (lastquote != NULL)
*lastquote = '\0';
}
if (arg[i + 1] == '?' || arg[i + 1] == '[' ||
arg[i + 1] == '*' || arg[i + 1] == '\\') {
/*
* Special case for sftp: append
* escaped glob sequence -
* glob will undo one level of
* escaping.
*/
argvs[j++] = arg[i++];
argvs[j++] = arg[i];
} else {
/* Unescape everything */
/* XXX support \n and friends? */
i++;
argvs[j++] = arg[i];
}
}
} else if (arg[i] == '#') {
if (state == MA_SQUOTE || state == MA_DQUOTE)
argvs[j++] = arg[i];
else
goto string_done;
} else if (arg[i] == '\0') {
if (state == MA_SQUOTE || state == MA_DQUOTE) {
if (sloppy) {
state = MA_UNQUOTED;
if (terminated != NULL)
*terminated = 0;
goto string_done;
}
error("Unterminated quoted argument");
return NULL;
}
string_done:
if (state == MA_UNQUOTED) {
argvs[j++] = '\0';
argc++;
}
break;
} else {
if (state == MA_START) {
argv[argc] = argvs + j;
state = MA_UNQUOTED;
if (lastquote != NULL)
*lastquote = '\0';
}
if ((state == MA_SQUOTE || state == MA_DQUOTE) &&
(arg[i] == '?' || arg[i] == '[' || arg[i] == '*')) {
/*
* Special case for sftp: escape quoted
* glob(3) wildcards. NB. string can grow
* here.
*/
if (j >= sizeof(argvs) - 3)
goto args_too_longs;
argvs[j++] = '\\';
argvs[j++] = arg[i];
} else
argvs[j++] = arg[i];
}
i++;
}
*argcp = argc;
return argv;
}
static int
-parse_args(const char **cpp, int *ignore_errors, int *aflag,
+parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
int *rflag, int *sflag,
unsigned long *n_arg, char **path1, char **path2)
{
const char *cmd, *cp = *cpp;
char *cp2, **argv;
int base = 0;
long l;
int path1_mandatory = 0, i, cmdnum, optidx, argc;
/* Skip leading whitespace */
cp = cp + strspn(cp, WHITESPACE);
- /* Check for leading '-' (disable error processing) */
+ /*
+ * Check for leading '-' (disable error processing) and '@' (suppress
+ * command echo)
+ */
*ignore_errors = 0;
- if (*cp == '-') {
- *ignore_errors = 1;
- cp++;
- cp = cp + strspn(cp, WHITESPACE);
+ *disable_echo = 0;
+ for (;*cp != '\0'; cp++) {
+ if (*cp == '-') {
+ *ignore_errors = 1;
+ } else if (*cp == '@') {
+ *disable_echo = 1;
+ } else {
+ /* all other characters terminate prefix processing */
+ break;
+ }
}
+ cp = cp + strspn(cp, WHITESPACE);
/* Ignore blank lines and lines which begin with comment '#' char */
if (*cp == '\0' || *cp == '#')
return (0);
if ((argv = makeargv(cp, &argc, 0, NULL, NULL)) == NULL)
return -1;
/* Figure out which command we have */
for (i = 0; cmds[i].c != NULL; i++) {
if (argv[0] != NULL && strcasecmp(cmds[i].c, argv[0]) == 0)
break;
}
cmdnum = cmds[i].n;
cmd = cmds[i].c;
/* Special case */
if (*cp == '!') {
cp++;
cmdnum = I_SHELL;
} else if (cmdnum == -1) {
error("Invalid command.");
return -1;
}
/* Get arguments and parse flags */
*aflag = *fflag = *hflag = *iflag = *lflag = *pflag = 0;
*rflag = *sflag = 0;
*path1 = *path2 = NULL;
optidx = 1;
switch (cmdnum) {
case I_GET:
case I_REGET:
case I_REPUT:
case I_PUT:
if ((optidx = parse_getput_flags(cmd, argv, argc,
aflag, fflag, pflag, rflag)) == -1)
return -1;
/* Get first pathname (mandatory) */
if (argc - optidx < 1) {
error("You must specify at least one path after a "
"%s command.", cmd);
return -1;
}
*path1 = xstrdup(argv[optidx]);
/* Get second pathname (optional) */
if (argc - optidx > 1) {
*path2 = xstrdup(argv[optidx + 1]);
/* Destination is not globbed */
undo_glob_escape(*path2);
}
break;
case I_LINK:
if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
return -1;
goto parse_two_paths;
case I_RENAME:
if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1)
return -1;
goto parse_two_paths;
case I_SYMLINK:
if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
return -1;
parse_two_paths:
if (argc - optidx < 2) {
error("You must specify two paths after a %s "
"command.", cmd);
return -1;
}
*path1 = xstrdup(argv[optidx]);
*path2 = xstrdup(argv[optidx + 1]);
/* Paths are not globbed */
undo_glob_escape(*path1);
undo_glob_escape(*path2);
break;
case I_RM:
case I_MKDIR:
case I_RMDIR:
case I_LMKDIR:
path1_mandatory = 1;
/* FALLTHROUGH */
case I_CHDIR:
case I_LCHDIR:
if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
return -1;
/* Get pathname (mandatory) */
if (argc - optidx < 1) {
if (!path1_mandatory)
break; /* return a NULL path1 */
error("You must specify a path after a %s command.",
cmd);
return -1;
}
*path1 = xstrdup(argv[optidx]);
/* Only "rm" globs */
if (cmdnum != I_RM)
undo_glob_escape(*path1);
break;
case I_DF:
if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
iflag)) == -1)
return -1;
/* Default to current directory if no path specified */
if (argc - optidx < 1)
*path1 = NULL;
else {
*path1 = xstrdup(argv[optidx]);
undo_glob_escape(*path1);
}
break;
case I_LS:
if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
return(-1);
/* Path is optional */
if (argc - optidx > 0)
*path1 = xstrdup(argv[optidx]);
break;
case I_LLS:
/* Skip ls command and following whitespace */
cp = cp + strlen(cmd) + strspn(cp, WHITESPACE);
case I_SHELL:
/* Uses the rest of the line */
break;
case I_LUMASK:
case I_CHMOD:
base = 8;
/* FALLTHROUGH */
case I_CHOWN:
case I_CHGRP:
- if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
+ if ((optidx = parse_ch_flags(cmd, argv, argc, hflag)) == -1)
return -1;
/* Get numeric arg (mandatory) */
if (argc - optidx < 1)
goto need_num_arg;
errno = 0;
l = strtol(argv[optidx], &cp2, base);
if (cp2 == argv[optidx] || *cp2 != '\0' ||
((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
l < 0) {
need_num_arg:
error("You must supply a numeric argument "
"to the %s command.", cmd);
return -1;
}
*n_arg = l;
if (cmdnum == I_LUMASK)
break;
/* Get pathname (mandatory) */
if (argc - optidx < 2) {
error("You must specify a path after a %s command.",
cmd);
return -1;
}
*path1 = xstrdup(argv[optidx + 1]);
break;
case I_QUIT:
case I_PWD:
case I_LPWD:
case I_HELP:
case I_VERSION:
case I_PROGRESS:
if ((optidx = parse_no_flags(cmd, argv, argc)) == -1)
return -1;
break;
default:
fatal("Command not implemented");
}
*cpp = cp;
return(cmdnum);
}
static int
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
- const char *startdir, int err_abort)
+ const char *startdir, int err_abort, int echo_command)
{
+ const char *ocmd = cmd;
char *path1, *path2, *tmp;
- int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0,
- iflag = 0;
+ int ignore_errors = 0, disable_echo = 1;
+ int aflag = 0, fflag = 0, hflag = 0, iflag = 0;
int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
int cmdnum, i;
unsigned long n_arg = 0;
Attrib a, *aa;
char path_buf[PATH_MAX];
int err = 0;
glob_t g;
path1 = path2 = NULL;
- cmdnum = parse_args(&cmd, &ignore_errors, &aflag, &fflag, &hflag,
- &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg, &path1, &path2);
+ cmdnum = parse_args(&cmd, &ignore_errors, &disable_echo, &aflag, &fflag,
+ &hflag, &iflag, &lflag, &pflag, &rflag, &sflag, &n_arg,
+ &path1, &path2);
if (ignore_errors != 0)
err_abort = 0;
+ if (echo_command && !disable_echo)
+ mprintf("sftp> %s\n", ocmd);
+
memset(&g, 0, sizeof(g));
/* Perform command */
switch (cmdnum) {
case 0:
/* Blank line */
break;
case -1:
/* Unrecognized command */
err = -1;
break;
case I_REGET:
aflag = 1;
/* FALLTHROUGH */
case I_GET:
err = process_get(conn, path1, path2, *pwd, pflag,
rflag, aflag, fflag);
break;
case I_REPUT:
aflag = 1;
/* FALLTHROUGH */
case I_PUT:
err = process_put(conn, path1, path2, *pwd, pflag,
rflag, aflag, fflag);
break;
case I_RENAME:
path1 = make_absolute(path1, *pwd);
path2 = make_absolute(path2, *pwd);
err = do_rename(conn, path1, path2, lflag);
break;
case I_SYMLINK:
sflag = 1;
/* FALLTHROUGH */
case I_LINK:
if (!sflag)
path1 = make_absolute(path1, *pwd);
path2 = make_absolute(path2, *pwd);
err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
break;
case I_RM:
path1 = make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
if (!quiet)
mprintf("Removing %s\n", g.gl_pathv[i]);
err = do_rm(conn, g.gl_pathv[i]);
if (err != 0 && err_abort)
break;
}
break;
case I_MKDIR:
path1 = make_absolute(path1, *pwd);
attrib_clear(&a);
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
a.perm = 0777;
err = do_mkdir(conn, path1, &a, 1);
break;
case I_RMDIR:
path1 = make_absolute(path1, *pwd);
err = do_rmdir(conn, path1);
break;
case I_CHDIR:
if (path1 == NULL || *path1 == '\0')
path1 = xstrdup(startdir);
path1 = make_absolute(path1, *pwd);
if ((tmp = do_realpath(conn, path1)) == NULL) {
err = 1;
break;
}
if ((aa = do_stat(conn, tmp, 0)) == NULL) {
free(tmp);
err = 1;
break;
}
if (!(aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) {
error("Can't change directory: Can't check target");
free(tmp);
err = 1;
break;
}
if (!S_ISDIR(aa->perm)) {
error("Can't change directory: \"%s\" is not "
"a directory", tmp);
free(tmp);
err = 1;
break;
}
free(*pwd);
*pwd = tmp;
break;
case I_LS:
if (!path1) {
do_ls_dir(conn, *pwd, *pwd, lflag);
break;
}
/* Strip pwd off beginning of non-absolute paths */
tmp = NULL;
- if (*path1 != '/')
+ if (!path_absolute(path1))
tmp = *pwd;
path1 = make_absolute(path1, *pwd);
err = do_globbed_ls(conn, path1, tmp, lflag);
break;
case I_DF:
/* Default to current directory if no path specified */
if (path1 == NULL)
path1 = xstrdup(*pwd);
path1 = make_absolute(path1, *pwd);
err = do_df(conn, path1, hflag, iflag);
break;
case I_LCHDIR:
if (path1 == NULL || *path1 == '\0')
path1 = xstrdup("~");
tmp = tilde_expand_filename(path1, getuid());
free(path1);
path1 = tmp;
if (chdir(path1) == -1) {
error("Couldn't change local directory to "
"\"%s\": %s", path1, strerror(errno));
err = 1;
}
break;
case I_LMKDIR:
if (mkdir(path1, 0777) == -1) {
error("Couldn't create local directory "
"\"%s\": %s", path1, strerror(errno));
err = 1;
}
break;
case I_LLS:
local_do_ls(cmd);
break;
case I_SHELL:
local_do_shell(cmd);
break;
case I_LUMASK:
umask(n_arg);
printf("Local umask: %03lo\n", n_arg);
break;
case I_CHMOD:
path1 = make_absolute(path1, *pwd);
attrib_clear(&a);
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
a.perm = n_arg;
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
if (!quiet)
mprintf("Changing mode on %s\n",
g.gl_pathv[i]);
- err = do_setstat(conn, g.gl_pathv[i], &a);
+ err = (hflag ? do_lsetstat : do_setstat)(conn,
+ g.gl_pathv[i], &a);
if (err != 0 && err_abort)
break;
}
break;
case I_CHOWN:
case I_CHGRP:
path1 = make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
- if (!(aa = do_stat(conn, g.gl_pathv[i], 0))) {
+ if (!(aa = (hflag ? do_lstat : do_stat)(conn,
+ g.gl_pathv[i], 0))) {
if (err_abort) {
err = -1;
break;
} else
continue;
}
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
error("Can't get current ownership of "
"remote file \"%s\"", g.gl_pathv[i]);
if (err_abort) {
err = -1;
break;
} else
continue;
}
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
if (cmdnum == I_CHOWN) {
if (!quiet)
mprintf("Changing owner on %s\n",
g.gl_pathv[i]);
aa->uid = n_arg;
} else {
if (!quiet)
mprintf("Changing group on %s\n",
g.gl_pathv[i]);
aa->gid = n_arg;
}
- err = do_setstat(conn, g.gl_pathv[i], aa);
+ err = (hflag ? do_lsetstat : do_setstat)(conn,
+ g.gl_pathv[i], aa);
if (err != 0 && err_abort)
break;
}
break;
case I_PWD:
mprintf("Remote working directory: %s\n", *pwd);
break;
case I_LPWD:
if (!getcwd(path_buf, sizeof(path_buf))) {
error("Couldn't get local cwd: %s", strerror(errno));
err = -1;
break;
}
mprintf("Local working directory: %s\n", path_buf);
break;
case I_QUIT:
/* Processed below */
break;
case I_HELP:
help();
break;
case I_VERSION:
printf("SFTP protocol version %u\n", sftp_proto_version(conn));
break;
case I_PROGRESS:
showprogress = !showprogress;
if (showprogress)
printf("Progress meter enabled\n");
else
printf("Progress meter disabled\n");
break;
default:
fatal("%d is not implemented", cmdnum);
}
if (g.gl_pathc)
globfree(&g);
free(path1);
free(path2);
/* If an unignored error occurs in batch mode we should abort. */
if (err_abort && err != 0)
return (-1);
else if (cmdnum == I_QUIT)
return (1);
return (0);
}
#ifdef USE_LIBEDIT
static char *
prompt(EditLine *el)
{
return ("sftp> ");
}
/* Display entries in 'list' after skipping the first 'len' chars */
static void
complete_display(char **list, u_int len)
{
u_int y, m = 0, width = 80, columns = 1, colspace = 0, llen;
struct winsize ws;
char *tmp;
/* Count entries for sort and find longest */
for (y = 0; list[y]; y++)
m = MAXIMUM(m, strlen(list[y]));
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1)
width = ws.ws_col;
m = m > len ? m - len : 0;
columns = width / (m + 2);
columns = MAXIMUM(columns, 1);
colspace = width / columns;
colspace = MINIMUM(colspace, width);
printf("\n");
m = 1;
for (y = 0; list[y]; y++) {
llen = strlen(list[y]);
tmp = llen > len ? list[y] + len : "";
mprintf("%-*s", colspace, tmp);
if (m >= columns) {
printf("\n");
m = 1;
} else
m++;
}
printf("\n");
}
/*
* Given a "list" of words that begin with a common prefix of "word",
* attempt to find an autocompletion to extends "word" by the next
* characters common to all entries in "list".
*/
static char *
complete_ambiguous(const char *word, char **list, size_t count)
{
if (word == NULL)
return NULL;
if (count > 0) {
u_int y, matchlen = strlen(list[0]);
/* Find length of common stem */
for (y = 1; list[y]; y++) {
u_int x;
for (x = 0; x < matchlen; x++)
if (list[0][x] != list[y][x])
break;
matchlen = x;
}
if (matchlen > strlen(word)) {
char *tmp = xstrdup(list[0]);
tmp[matchlen] = '\0';
return tmp;
}
}
return xstrdup(word);
}
/* Autocomplete a sftp command */
static int
complete_cmd_parse(EditLine *el, char *cmd, int lastarg, char quote,
int terminated)
{
u_int y, count = 0, cmdlen, tmplen;
char *tmp, **list, argterm[3];
const LineInfo *lf;
list = xcalloc((sizeof(cmds) / sizeof(*cmds)) + 1, sizeof(char *));
/* No command specified: display all available commands */
if (cmd == NULL) {
for (y = 0; cmds[y].c; y++)
list[count++] = xstrdup(cmds[y].c);
list[count] = NULL;
complete_display(list, 0);
for (y = 0; list[y] != NULL; y++)
free(list[y]);
free(list);
return count;
}
/* Prepare subset of commands that start with "cmd" */
cmdlen = strlen(cmd);
for (y = 0; cmds[y].c; y++) {
if (!strncasecmp(cmd, cmds[y].c, cmdlen))
list[count++] = xstrdup(cmds[y].c);
}
list[count] = NULL;
if (count == 0) {
free(list);
return 0;
}
/* Complete ambiguous command */
tmp = complete_ambiguous(cmd, list, count);
if (count > 1)
complete_display(list, 0);
for (y = 0; list[y]; y++)
free(list[y]);
free(list);
if (tmp != NULL) {
tmplen = strlen(tmp);
cmdlen = strlen(cmd);
/* If cmd may be extended then do so */
if (tmplen > cmdlen)
if (el_insertstr(el, tmp + cmdlen) == -1)
fatal("el_insertstr failed.");
lf = el_line(el);
/* Terminate argument cleanly */
if (count == 1) {
y = 0;
if (!terminated)
argterm[y++] = quote;
if (lastarg || *(lf->cursor) != ' ')
argterm[y++] = ' ';
argterm[y] = '\0';
if (y > 0 && el_insertstr(el, argterm) == -1)
fatal("el_insertstr failed.");
}
free(tmp);
}
return count;
}
/*
* Determine whether a particular sftp command's arguments (if any)
* represent local or remote files.
*/
static int
complete_is_remote(char *cmd) {
int i;
if (cmd == NULL)
return -1;
for (i = 0; cmds[i].c; i++) {
if (!strncasecmp(cmd, cmds[i].c, strlen(cmds[i].c)))
return cmds[i].t;
}
return -1;
}
/* Autocomplete a filename "file" */
static int
complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
char *file, int remote, int lastarg, char quote, int terminated)
{
glob_t g;
char *tmp, *tmp2, ins[8];
u_int i, hadglob, pwdlen, len, tmplen, filelen, cesc, isesc, isabs;
int clen;
const LineInfo *lf;
/* Glob from "file" location */
if (file == NULL)
tmp = xstrdup("*");
else
xasprintf(&tmp, "%s*", file);
/* Check if the path is absolute. */
- isabs = tmp[0] == '/';
+ isabs = path_absolute(tmp);
memset(&g, 0, sizeof(g));
if (remote != LOCAL) {
tmp = make_absolute(tmp, remote_path);
remote_glob(conn, tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
} else
glob(tmp, GLOB_DOOFFS|GLOB_MARK, NULL, &g);
/* Determine length of pwd so we can trim completion display */
for (hadglob = tmplen = pwdlen = 0; tmp[tmplen] != 0; tmplen++) {
/* Terminate counting on first unescaped glob metacharacter */
if (tmp[tmplen] == '*' || tmp[tmplen] == '?') {
if (tmp[tmplen] != '*' || tmp[tmplen + 1] != '\0')
hadglob = 1;
break;
}
if (tmp[tmplen] == '\\' && tmp[tmplen + 1] != '\0')
tmplen++;
if (tmp[tmplen] == '/')
pwdlen = tmplen + 1; /* track last seen '/' */
}
free(tmp);
tmp = NULL;
if (g.gl_matchc == 0)
goto out;
if (g.gl_matchc > 1)
complete_display(g.gl_pathv, pwdlen);
/* Don't try to extend globs */
if (file == NULL || hadglob)
goto out;
tmp2 = complete_ambiguous(file, g.gl_pathv, g.gl_matchc);
tmp = path_strip(tmp2, isabs ? NULL : remote_path);
free(tmp2);
if (tmp == NULL)
goto out;
tmplen = strlen(tmp);
filelen = strlen(file);
/* Count the number of escaped characters in the input string. */
cesc = isesc = 0;
for (i = 0; i < filelen; i++) {
if (!isesc && file[i] == '\\' && i + 1 < filelen){
isesc = 1;
cesc++;
} else
isesc = 0;
}
if (tmplen > (filelen - cesc)) {
tmp2 = tmp + filelen - cesc;
len = strlen(tmp2);
/* quote argument on way out */
for (i = 0; i < len; i += clen) {
if ((clen = mblen(tmp2 + i, len - i)) < 0 ||
(size_t)clen > sizeof(ins) - 2)
fatal("invalid multibyte character");
ins[0] = '\\';
memcpy(ins + 1, tmp2 + i, clen);
ins[clen + 1] = '\0';
switch (tmp2[i]) {
case '\'':
case '"':
case '\\':
case '\t':
case '[':
case ' ':
case '#':
case '*':
if (quote == '\0' || tmp2[i] == quote) {
if (el_insertstr(el, ins) == -1)
fatal("el_insertstr "
"failed.");
break;
}
/* FALLTHROUGH */
default:
if (el_insertstr(el, ins + 1) == -1)
fatal("el_insertstr failed.");
break;
}
}
}
lf = el_line(el);
if (g.gl_matchc == 1) {
i = 0;
if (!terminated && quote != '\0')
ins[i++] = quote;
if (*(lf->cursor - 1) != '/' &&
(lastarg || *(lf->cursor) != ' '))
ins[i++] = ' ';
ins[i] = '\0';
if (i > 0 && el_insertstr(el, ins) == -1)
fatal("el_insertstr failed.");
}
free(tmp);
out:
globfree(&g);
return g.gl_matchc;
}
/* tab-completion hook function, called via libedit */
static unsigned char
complete(EditLine *el, int ch)
{
char **argv, *line, quote;
int argc, carg;
u_int cursor, len, terminated, ret = CC_ERROR;
const LineInfo *lf;
struct complete_ctx *complete_ctx;
lf = el_line(el);
if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0)
fatal("%s: el_get failed", __func__);
/* Figure out which argument the cursor points to */
cursor = lf->cursor - lf->buffer;
line = xmalloc(cursor + 1);
memcpy(line, lf->buffer, cursor);
line[cursor] = '\0';
argv = makeargv(line, &carg, 1, &quote, &terminated);
free(line);
/* Get all the arguments on the line */
len = lf->lastchar - lf->buffer;
line = xmalloc(len + 1);
memcpy(line, lf->buffer, len);
line[len] = '\0';
argv = makeargv(line, &argc, 1, NULL, NULL);
/* Ensure cursor is at EOL or a argument boundary */
if (line[cursor] != ' ' && line[cursor] != '\0' &&
line[cursor] != '\n') {
free(line);
return ret;
}
if (carg == 0) {
/* Show all available commands */
complete_cmd_parse(el, NULL, argc == carg, '\0', 1);
ret = CC_REDISPLAY;
} else if (carg == 1 && cursor > 0 && line[cursor - 1] != ' ') {
/* Handle the command parsing */
if (complete_cmd_parse(el, argv[0], argc == carg,
quote, terminated) != 0)
ret = CC_REDISPLAY;
} else if (carg >= 1) {
/* Handle file parsing */
int remote = complete_is_remote(argv[0]);
char *filematch = NULL;
if (carg > 1 && line[cursor-1] != ' ')
filematch = argv[carg - 1];
if (remote != 0 &&
complete_match(el, complete_ctx->conn,
*complete_ctx->remote_pathp, filematch,
remote, carg == argc, quote, terminated) != 0)
ret = CC_REDISPLAY;
}
free(line);
return ret;
}
#endif /* USE_LIBEDIT */
static int
interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
{
char *remote_path;
char *dir = NULL, *startdir = NULL;
char cmd[2048];
int err, interactive;
EditLine *el = NULL;
#ifdef USE_LIBEDIT
History *hl = NULL;
HistEvent hev;
extern char *__progname;
struct complete_ctx complete_ctx;
if (!batchmode && isatty(STDIN_FILENO)) {
if ((el = el_init(__progname, stdin, stdout, stderr)) == NULL)
fatal("Couldn't initialise editline");
if ((hl = history_init()) == NULL)
fatal("Couldn't initialise editline history");
history(hl, &hev, H_SETSIZE, 100);
el_set(el, EL_HIST, history, hl);
el_set(el, EL_PROMPT, prompt);
el_set(el, EL_EDITOR, "emacs");
el_set(el, EL_TERMINAL, NULL);
el_set(el, EL_SIGNAL, 1);
el_source(el, NULL);
/* Tab Completion */
el_set(el, EL_ADDFN, "ftp-complete",
"Context sensitive argument completion", complete);
complete_ctx.conn = conn;
complete_ctx.remote_pathp = &remote_path;
el_set(el, EL_CLIENTDATA, (void*)&complete_ctx);
el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
/* enable ctrl-left-arrow and ctrl-right-arrow */
el_set(el, EL_BIND, "\\e[1;5C", "em-next-word", NULL);
el_set(el, EL_BIND, "\\e[5C", "em-next-word", NULL);
el_set(el, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL);
el_set(el, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL);
/* make ^w match ksh behaviour */
el_set(el, EL_BIND, "^w", "ed-delete-prev-word", NULL);
}
#endif /* USE_LIBEDIT */
remote_path = do_realpath(conn, ".");
if (remote_path == NULL)
fatal("Need cwd");
startdir = xstrdup(remote_path);
if (file1 != NULL) {
dir = xstrdup(file1);
dir = make_absolute(dir, remote_path);
if (remote_is_dir(conn, dir) && file2 == NULL) {
if (!quiet)
mprintf("Changing to: %s\n", dir);
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
if (parse_dispatch_command(conn, cmd,
- &remote_path, startdir, 1) != 0) {
+ &remote_path, startdir, 1, 0) != 0) {
free(dir);
free(startdir);
free(remote_path);
free(conn);
return (-1);
}
} else {
/* XXX this is wrong wrt quoting */
snprintf(cmd, sizeof cmd, "get%s %s%s%s",
global_aflag ? " -a" : "", dir,
file2 == NULL ? "" : " ",
file2 == NULL ? "" : file2);
err = parse_dispatch_command(conn, cmd,
- &remote_path, startdir, 1);
+ &remote_path, startdir, 1, 0);
free(dir);
free(startdir);
free(remote_path);
free(conn);
return (err);
}
free(dir);
}
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(infile, NULL, _IOLBF, 0);
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
for (;;) {
- char *cp;
-
signal(SIGINT, SIG_IGN);
if (el == NULL) {
if (interactive)
printf("sftp> ");
if (fgets(cmd, sizeof(cmd), infile) == NULL) {
if (interactive)
printf("\n");
break;
}
- if (!interactive) { /* Echo command */
- mprintf("sftp> %s", cmd);
- if (strlen(cmd) > 0 &&
- cmd[strlen(cmd) - 1] != '\n')
- printf("\n");
- }
} else {
#ifdef USE_LIBEDIT
const char *line;
int count = 0;
if ((line = el_gets(el, &count)) == NULL ||
count <= 0) {
printf("\n");
break;
}
history(hl, &hev, H_ENTER, line);
if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
fprintf(stderr, "Error: input line too long\n");
continue;
}
#endif /* USE_LIBEDIT */
}
- cp = strrchr(cmd, '\n');
- if (cp)
- *cp = '\0';
+ cmd[strcspn(cmd, "\n")] = '\0';
/* Handle user interrupts gracefully during commands */
interrupted = 0;
signal(SIGINT, cmd_interrupt);
err = parse_dispatch_command(conn, cmd, &remote_path,
- startdir, batchmode);
+ startdir, batchmode, !interactive && el == NULL);
if (err != 0)
break;
}
signal(SIGCHLD, SIG_DFL);
free(remote_path);
free(startdir);
free(conn);
#ifdef USE_LIBEDIT
if (el != NULL)
el_end(el);
#endif /* USE_LIBEDIT */
/* err == 1 signifies normal "quit" exit */
return (err >= 0 ? 0 : -1);
}
static void
connect_to_server(char *path, char **args, int *in, int *out)
{
int c_in, c_out;
#ifdef USE_PIPES
int pin[2], pout[2];
if ((pipe(pin) == -1) || (pipe(pout) == -1))
fatal("pipe: %s", strerror(errno));
*in = pin[0];
*out = pout[1];
c_in = pout[0];
c_out = pin[1];
#else /* USE_PIPES */
int inout[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1)
fatal("socketpair: %s", strerror(errno));
*in = *out = inout[0];
c_in = c_out = inout[1];
#endif /* USE_PIPES */
if ((sshpid = fork()) == -1)
fatal("fork: %s", strerror(errno));
else if (sshpid == 0) {
if ((dup2(c_in, STDIN_FILENO) == -1) ||
(dup2(c_out, STDOUT_FILENO) == -1)) {
fprintf(stderr, "dup2: %s\n", strerror(errno));
_exit(1);
}
close(*in);
close(*out);
close(c_in);
close(c_out);
/*
* The underlying ssh is in the same process group, so we must
* ignore SIGINT if we want to gracefully abort commands,
* otherwise the signal will make it to the ssh process and
* kill it too. Contrawise, since sftp sends SIGTERMs to the
* underlying ssh, it must *not* ignore that signal.
*/
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_DFL);
execvp(path, args);
fprintf(stderr, "exec: %s: %s\n", path, strerror(errno));
_exit(1);
}
signal(SIGTERM, killchild);
signal(SIGINT, killchild);
signal(SIGHUP, killchild);
signal(SIGTSTP, suspchild);
signal(SIGTTIN, suspchild);
signal(SIGTTOU, suspchild);
signal(SIGCHLD, sigchld_handler);
close(c_in);
close(c_out);
}
static void
usage(void)
{
extern char *__progname;
fprintf(stderr,
"usage: %s [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
- " [-D sftp_server_path] [-F ssh_config] "
- "[-i identity_file] [-l limit]\n"
- " [-o ssh_option] [-P port] [-R num_requests] "
- "[-S program]\n"
- " [-s subsystem | sftp_server] destination\n",
+ " [-D sftp_server_path] [-F ssh_config] [-i identity_file]\n"
+ " [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
+ " [-R num_requests] [-S program] [-s subsystem | sftp_server]\n"
+ " destination\n",
__progname);
exit(1);
}
int
main(int argc, char **argv)
{
int in, out, ch, err, tmp, port = -1;
char *host = NULL, *user, *cp, *file2 = NULL;
int debug_level = 0, sshver = 2;
char *file1 = NULL, *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
const char *errstr;
LogLevel ll = SYSLOG_LEVEL_INFO;
arglist args;
extern int optind;
extern char *optarg;
struct sftp_conn *conn;
size_t copy_buffer_len = DEFAULT_COPY_BUFLEN;
size_t num_requests = DEFAULT_NUM_REQUESTS;
long long limit_kbps = 0;
ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
msetlocale();
+ seed_rng();
+
__progname = ssh_get_progname(argv[0]);
memset(&args, '\0', sizeof(args));
args.list = NULL;
addargs(&args, "%s", ssh_program);
addargs(&args, "-oForwardX11 no");
addargs(&args, "-oForwardAgent no");
addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "-oClearAllForwardings yes");
ll = SYSLOG_LEVEL_INFO;
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:P:R:")) != -1) {
+ "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
case '4':
case '6':
case 'C':
addargs(&args, "-%c", ch);
break;
/* Passed through to ssh(1) with argument */
case 'F':
+ case 'J':
case 'c':
case 'i':
case 'o':
addargs(&args, "-%c", ch);
addargs(&args, "%s", optarg);
break;
case 'q':
ll = SYSLOG_LEVEL_ERROR;
quiet = 1;
showprogress = 0;
addargs(&args, "-%c", ch);
break;
case 'P':
port = a2port(optarg);
if (port <= 0)
fatal("Bad port \"%s\"\n", optarg);
break;
case 'v':
if (debug_level < 3) {
addargs(&args, "-v");
ll = SYSLOG_LEVEL_DEBUG1 + debug_level;
}
debug_level++;
break;
case '1':
sshver = 1;
if (sftp_server == NULL)
sftp_server = _PATH_SFTP_SERVER;
break;
case '2':
sshver = 2;
break;
case 'a':
global_aflag = 1;
break;
case 'B':
copy_buffer_len = strtol(optarg, &cp, 10);
if (copy_buffer_len == 0 || *cp != '\0')
fatal("Invalid buffer size \"%s\"", optarg);
break;
case 'b':
if (batchmode)
fatal("Batch file already specified.");
/* Allow "-" as stdin */
if (strcmp(optarg, "-") != 0 &&
(infile = fopen(optarg, "r")) == NULL)
fatal("%s (%s).", strerror(errno), optarg);
showprogress = 0;
quiet = batchmode = 1;
addargs(&args, "-obatchmode yes");
break;
case 'f':
global_fflag = 1;
break;
case 'p':
global_pflag = 1;
break;
case 'D':
sftp_direct = optarg;
break;
case 'l':
limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
&errstr);
if (errstr != NULL)
usage();
limit_kbps *= 1024; /* kbps */
break;
case 'r':
global_rflag = 1;
break;
case 'R':
num_requests = strtol(optarg, &cp, 10);
if (num_requests == 0 || *cp != '\0')
fatal("Invalid number of requests \"%s\"",
optarg);
break;
case 's':
sftp_server = optarg;
break;
case 'S':
ssh_program = optarg;
replacearg(&args, 0, "%s", ssh_program);
break;
case 'h':
default:
usage();
}
}
if (!isatty(STDERR_FILENO))
showprogress = 0;
log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
if (sftp_direct == NULL) {
if (optind == argc || argc > (optind + 2))
usage();
argv += optind;
switch (parse_uri("sftp", *argv, &user, &host, &tmp, &file1)) {
case -1:
usage();
break;
case 0:
if (tmp != -1)
port = tmp;
break;
default:
if (parse_user_host_path(*argv, &user, &host,
&file1) == -1) {
/* Treat as a plain hostname. */
host = xstrdup(*argv);
host = cleanhostname(host);
}
break;
}
file2 = *(argv + 1);
if (!*host) {
fprintf(stderr, "Missing hostname\n");
usage();
}
if (port != -1)
addargs(&args, "-oPort %d", port);
if (user != NULL) {
addargs(&args, "-l");
addargs(&args, "%s", user);
}
addargs(&args, "-oProtocol %d", sshver);
/* no subsystem if the server-spec contains a '/' */
if (sftp_server == NULL || strchr(sftp_server, '/') == NULL)
addargs(&args, "-s");
addargs(&args, "--");
addargs(&args, "%s", host);
addargs(&args, "%s", (sftp_server != NULL ?
sftp_server : "sftp"));
connect_to_server(ssh_program, args.list, &in, &out);
} else {
args.list = NULL;
addargs(&args, "sftp-server");
connect_to_server(sftp_direct, args.list, &in, &out);
}
freeargs(&args);
conn = do_init(in, out, copy_buffer_len, num_requests, limit_kbps);
if (conn == NULL)
fatal("Couldn't initialise connection to server");
if (!quiet) {
if (sftp_direct == NULL)
fprintf(stderr, "Connected to %s.\n", host);
else
fprintf(stderr, "Attached to %s.\n", sftp_direct);
}
err = interactive_loop(conn, file1, file2);
#if !defined(USE_PIPES)
shutdown(in, SHUT_RDWR);
shutdown(out, SHUT_RDWR);
#endif
close(in);
close(out);
if (batchmode)
fclose(infile);
while (waitpid(sshpid, NULL, 0) == -1 && sshpid > 1)
if (errno != EINTR)
fatal("Couldn't wait for ssh process: %s",
strerror(errno));
exit(err == 0 ? 0 : 1);
}
diff --git a/sntrup4591761.c b/sntrup4591761.c
new file mode 100644
index 000000000000..61fe2483f4fd
--- /dev/null
+++ b/sntrup4591761.c
@@ -0,0 +1,1083 @@
+/* $OpenBSD: sntrup4591761.c,v 1.3 2019/01/30 19:51:15 markus Exp $ */
+
+/*
+ * Public Domain, Authors:
+ * - Daniel J. Bernstein
+ * - Chitchanok Chuengsatiansup
+ * - Tanja Lange
+ * - Christine van Vredendaal
+ */
+
+#include "includes.h"
+
+#include <string.h>
+#include "crypto_api.h"
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.h */
+#ifndef int32_sort_h
+#define int32_sort_h
+
+
+static void int32_sort(crypto_int32 *,int);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void minmax(crypto_int32 *x,crypto_int32 *y)
+{
+ crypto_uint32 xi = *x;
+ crypto_uint32 yi = *y;
+ crypto_uint32 xy = xi ^ yi;
+ crypto_uint32 c = yi - xi;
+ c ^= xy & (c ^ yi);
+ c >>= 31;
+ c = -c;
+ c &= xy;
+ *x = xi ^ c;
+ *y = yi ^ c;
+}
+
+static void int32_sort(crypto_int32 *x,int n)
+{
+ int top,p,q,i;
+
+ if (n < 2) return;
+ top = 1;
+ while (top < n - top) top += top;
+
+ for (p = top;p > 0;p >>= 1) {
+ for (i = 0;i < n - p;++i)
+ if (!(i & p))
+ minmax(x + i,x + i + p);
+ for (q = top;q > p;q >>= 1)
+ for (i = 0;i < n - q;++i)
+ if (!(i & p))
+ minmax(x + i + p,x + i + q);
+ }
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.h */
+#ifndef small_h
+#define small_h
+
+
+typedef crypto_int8 small;
+
+static void small_encode(unsigned char *,const small *);
+
+static void small_decode(small *,const unsigned char *);
+
+
+static void small_random(small *);
+
+static void small_random_weightw(small *);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/mod3.h */
+#ifndef mod3_h
+#define mod3_h
+
+
+/* -1 if x is nonzero, 0 otherwise */
+static inline int mod3_nonzero_mask(small x)
+{
+ return -x*x;
+}
+
+/* input between -100000 and 100000 */
+/* output between -1 and 1 */
+static inline small mod3_freeze(crypto_int32 a)
+{
+ a -= 3 * ((10923 * a) >> 15);
+ a -= 3 * ((89478485 * a + 134217728) >> 28);
+ return a;
+}
+
+static inline small mod3_minusproduct(small a,small b,small c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return mod3_freeze(A - B * C);
+}
+
+static inline small mod3_plusproduct(small a,small b,small c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return mod3_freeze(A + B * C);
+}
+
+static inline small mod3_product(small a,small b)
+{
+ return a * b;
+}
+
+static inline small mod3_sum(small a,small b)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ return mod3_freeze(A + B);
+}
+
+static inline small mod3_reciprocal(small a1)
+{
+ return a1;
+}
+
+static inline small mod3_quotient(small num,small den)
+{
+ return mod3_product(num,mod3_reciprocal(den));
+}
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/modq.h */
+#ifndef modq_h
+#define modq_h
+
+
+typedef crypto_int16 modq;
+
+/* -1 if x is nonzero, 0 otherwise */
+static inline int modq_nonzero_mask(modq x)
+{
+ crypto_int32 r = (crypto_uint16) x;
+ r = -r;
+ r >>= 30;
+ return r;
+}
+
+/* input between -9000000 and 9000000 */
+/* output between -2295 and 2295 */
+static inline modq modq_freeze(crypto_int32 a)
+{
+ a -= 4591 * ((228 * a) >> 20);
+ a -= 4591 * ((58470 * a + 134217728) >> 28);
+ return a;
+}
+
+static inline modq modq_minusproduct(modq a,modq b,modq c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return modq_freeze(A - B * C);
+}
+
+static inline modq modq_plusproduct(modq a,modq b,modq c)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ crypto_int32 C = c;
+ return modq_freeze(A + B * C);
+}
+
+static inline modq modq_product(modq a,modq b)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ return modq_freeze(A * B);
+}
+
+static inline modq modq_square(modq a)
+{
+ crypto_int32 A = a;
+ return modq_freeze(A * A);
+}
+
+static inline modq modq_sum(modq a,modq b)
+{
+ crypto_int32 A = a;
+ crypto_int32 B = b;
+ return modq_freeze(A + B);
+}
+
+static inline modq modq_reciprocal(modq a1)
+{
+ modq a2 = modq_square(a1);
+ modq a3 = modq_product(a2,a1);
+ modq a4 = modq_square(a2);
+ modq a8 = modq_square(a4);
+ modq a16 = modq_square(a8);
+ modq a32 = modq_square(a16);
+ modq a35 = modq_product(a32,a3);
+ modq a70 = modq_square(a35);
+ modq a140 = modq_square(a70);
+ modq a143 = modq_product(a140,a3);
+ modq a286 = modq_square(a143);
+ modq a572 = modq_square(a286);
+ modq a1144 = modq_square(a572);
+ modq a1147 = modq_product(a1144,a3);
+ modq a2294 = modq_square(a1147);
+ modq a4588 = modq_square(a2294);
+ modq a4589 = modq_product(a4588,a1);
+ return a4589;
+}
+
+static inline modq modq_quotient(modq num,modq den)
+{
+ return modq_product(num,modq_reciprocal(den));
+}
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/params.h */
+#ifndef params_h
+#define params_h
+
+#define q 4591
+/* XXX: also built into modq in various ways */
+
+#define qshift 2295
+#define p 761
+#define w 286
+
+#define rq_encode_len 1218
+#define small_encode_len 191
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3.h */
+#ifndef r3_h
+#define r3_h
+
+
+static void r3_mult(small *,const small *,const small *);
+
+extern int r3_recip(small *,const small *);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.h */
+#ifndef rq_h
+#define rq_h
+
+
+static void rq_encode(unsigned char *,const modq *);
+
+static void rq_decode(modq *,const unsigned char *);
+
+static void rq_encoderounded(unsigned char *,const modq *);
+
+static void rq_decoderounded(modq *,const unsigned char *);
+
+static void rq_round3(modq *,const modq *);
+
+static void rq_mult(modq *,const modq *,const small *);
+
+int rq_recip3(modq *,const small *);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.h */
+#ifndef swap_h
+#define swap_h
+
+static void swap(void *,void *,int,int);
+
+#endif
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/dec.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+#ifdef KAT
+#endif
+
+
+int crypto_kem_sntrup4591761_dec(
+ unsigned char *k,
+ const unsigned char *cstr,
+ const unsigned char *sk
+)
+{
+ small f[p];
+ modq h[p];
+ small grecip[p];
+ modq c[p];
+ modq t[p];
+ small t3[p];
+ small r[p];
+ modq hr[p];
+ unsigned char rstr[small_encode_len];
+ unsigned char hash[64];
+ int i;
+ int result = 0;
+ int weight;
+
+ small_decode(f,sk);
+ small_decode(grecip,sk + small_encode_len);
+ rq_decode(h,sk + 2 * small_encode_len);
+
+ rq_decoderounded(c,cstr + 32);
+
+ rq_mult(t,c,f);
+ for (i = 0;i < p;++i) t3[i] = mod3_freeze(modq_freeze(3*t[i]));
+
+ r3_mult(r,t3,grecip);
+
+#ifdef KAT
+ {
+ int j;
+ printf("decrypt r:");
+ for (j = 0;j < p;++j)
+ if (r[j] == 1) printf(" +%d",j);
+ else if (r[j] == -1) printf(" -%d",j);
+ printf("\n");
+ }
+#endif
+
+ weight = 0;
+ for (i = 0;i < p;++i) weight += (1 & r[i]);
+ weight -= w;
+ result |= modq_nonzero_mask(weight); /* XXX: puts limit on p */
+
+ rq_mult(hr,h,r);
+ rq_round3(hr,hr);
+ for (i = 0;i < p;++i) result |= modq_nonzero_mask(hr[i] - c[i]);
+
+ small_encode(rstr,r);
+ crypto_hash_sha512(hash,rstr,sizeof rstr);
+ result |= crypto_verify_32(hash,cstr);
+
+ for (i = 0;i < 32;++i) k[i] = (hash[32 + i] & ~result);
+ return result;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/enc.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+#ifdef KAT
+#endif
+
+
+int crypto_kem_sntrup4591761_enc(
+ unsigned char *cstr,
+ unsigned char *k,
+ const unsigned char *pk
+)
+{
+ small r[p];
+ modq h[p];
+ modq c[p];
+ unsigned char rstr[small_encode_len];
+ unsigned char hash[64];
+
+ small_random_weightw(r);
+
+#ifdef KAT
+ {
+ int i;
+ printf("encrypt r:");
+ for (i = 0;i < p;++i)
+ if (r[i] == 1) printf(" +%d",i);
+ else if (r[i] == -1) printf(" -%d",i);
+ printf("\n");
+ }
+#endif
+
+ small_encode(rstr,r);
+ crypto_hash_sha512(hash,rstr,sizeof rstr);
+
+ rq_decode(h,pk);
+ rq_mult(c,h,r);
+ rq_round3(c,c);
+
+ memcpy(k,hash + 32,32);
+ memcpy(cstr,hash,32);
+ rq_encoderounded(cstr + 32,c);
+
+ return 0;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/keypair.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+#if crypto_kem_sntrup4591761_PUBLICKEYBYTES != rq_encode_len
+#error "crypto_kem_sntrup4591761_PUBLICKEYBYTES must match rq_encode_len"
+#endif
+#if crypto_kem_sntrup4591761_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len
+#error "crypto_kem_sntrup4591761_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len"
+#endif
+
+int crypto_kem_sntrup4591761_keypair(unsigned char *pk,unsigned char *sk)
+{
+ small g[p];
+ small grecip[p];
+ small f[p];
+ modq f3recip[p];
+ modq h[p];
+
+ do
+ small_random(g);
+ while (r3_recip(grecip,g) != 0);
+
+ small_random_weightw(f);
+ rq_recip3(f3recip,f);
+
+ rq_mult(h,f3recip,g);
+
+ rq_encode(pk,h);
+ small_encode(sk,f);
+ small_encode(sk + small_encode_len,grecip);
+ memcpy(sk + 2 * small_encode_len,pk,rq_encode_len);
+
+ return 0;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_mult.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void r3_mult(small *h,const small *f,const small *g)
+{
+ small fg[p + p - 1];
+ small result;
+ int i, j;
+
+ for (i = 0;i < p;++i) {
+ result = 0;
+ for (j = 0;j <= i;++j)
+ result = mod3_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+ for (i = p;i < p + p - 1;++i) {
+ result = 0;
+ for (j = i - p + 1;j < p;++j)
+ result = mod3_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+
+ for (i = p + p - 2;i >= p;--i) {
+ fg[i - p] = mod3_sum(fg[i - p],fg[i]);
+ fg[i - p + 1] = mod3_sum(fg[i - p + 1],fg[i]);
+ }
+
+ for (i = 0;i < p;++i)
+ h[i] = fg[i];
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_recip.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+/* caller must ensure that x-y does not overflow */
+static int smaller_mask_r3_recip(int x,int y)
+{
+ return (x - y) >> 31;
+}
+
+static void vectormod3_product(small *z,int len,const small *x,const small c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = mod3_product(x[i],c);
+}
+
+static void vectormod3_minusproduct(small *z,int len,const small *x,const small *y,const small c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = mod3_minusproduct(x[i],y[i],c);
+}
+
+static void vectormod3_shift(small *z,int len)
+{
+ int i;
+ for (i = len - 1;i > 0;--i) z[i] = z[i - 1];
+ z[0] = 0;
+}
+
+/*
+r = s^(-1) mod m, returning 0, if s is invertible mod m
+or returning -1 if s is not invertible mod m
+r,s are polys of degree <p
+m is x^p-x-1
+*/
+int r3_recip(small *r,const small *s)
+{
+ const int loops = 2*p + 1;
+ int loop;
+ small f[p + 1];
+ small g[p + 1];
+ small u[2*p + 2];
+ small v[2*p + 2];
+ small c;
+ int i;
+ int d = p;
+ int e = p;
+ int swapmask;
+
+ for (i = 2;i < p;++i) f[i] = 0;
+ f[0] = -1;
+ f[1] = -1;
+ f[p] = 1;
+ /* generalization: can initialize f to any polynomial m */
+ /* requirements: m has degree exactly p, nonzero constant coefficient */
+
+ for (i = 0;i < p;++i) g[i] = s[i];
+ g[p] = 0;
+
+ for (i = 0;i <= loops;++i) u[i] = 0;
+
+ v[0] = 1;
+ for (i = 1;i <= loops;++i) v[i] = 0;
+
+ loop = 0;
+ for (;;) {
+ /* e == -1 or d + e + loop <= 2*p */
+
+ /* f has degree p: i.e., f[p]!=0 */
+ /* f[i]==0 for i < p-d */
+
+ /* g has degree <=p (so it fits in p+1 coefficients) */
+ /* g[i]==0 for i < p-e */
+
+ /* u has degree <=loop (so it fits in loop+1 coefficients) */
+ /* u[i]==0 for i < p-d */
+ /* if invertible: u[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ /* v has degree <=loop (so it fits in loop+1 coefficients) */
+ /* v[i]==0 for i < p-e */
+ /* v[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ if (loop >= loops) break;
+
+ c = mod3_quotient(g[p],f[p]);
+
+ vectormod3_minusproduct(g,p + 1,g,f,c);
+ vectormod3_shift(g,p + 1);
+
+#ifdef SIMPLER
+ vectormod3_minusproduct(v,loops + 1,v,u,c);
+ vectormod3_shift(v,loops + 1);
+#else
+ if (loop < p) {
+ vectormod3_minusproduct(v,loop + 1,v,u,c);
+ vectormod3_shift(v,loop + 2);
+ } else {
+ vectormod3_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c);
+ vectormod3_shift(v + loop - p,p + 2);
+ }
+#endif
+
+ e -= 1;
+
+ ++loop;
+
+ swapmask = smaller_mask_r3_recip(e,d) & mod3_nonzero_mask(g[p]);
+ swap(&e,&d,sizeof e,swapmask);
+ swap(f,g,(p + 1) * sizeof(small),swapmask);
+
+#ifdef SIMPLER
+ swap(u,v,(loops + 1) * sizeof(small),swapmask);
+#else
+ if (loop < p) {
+ swap(u,v,(loop + 1) * sizeof(small),swapmask);
+ } else {
+ swap(u + loop - p,v + loop - p,(p + 1) * sizeof(small),swapmask);
+ }
+#endif
+ }
+
+ c = mod3_reciprocal(f[p]);
+ vectormod3_product(r,p,u + p,c);
+ return smaller_mask_r3_recip(0,d);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomsmall.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void small_random(small *g)
+{
+ int i;
+
+ for (i = 0;i < p;++i) {
+ crypto_uint32 r = small_random32();
+ g[i] = (small) (((1073741823 & r) * 3) >> 30) - 1;
+ }
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomweightw.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void small_random_weightw(small *f)
+{
+ crypto_int32 r[p];
+ int i;
+
+ for (i = 0;i < p;++i) r[i] = small_random32();
+ for (i = 0;i < w;++i) r[i] &= -2;
+ for (i = w;i < p;++i) r[i] = (r[i] & -3) | 1;
+ int32_sort(r,p);
+ for (i = 0;i < p;++i) f[i] = ((small) (r[i] & 3)) - 1;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_encode(unsigned char *c,const modq *f)
+{
+ crypto_int32 f0, f1, f2, f3, f4;
+ int i;
+
+ for (i = 0;i < p/5;++i) {
+ f0 = *f++ + qshift;
+ f1 = *f++ + qshift;
+ f2 = *f++ + qshift;
+ f3 = *f++ + qshift;
+ f4 = *f++ + qshift;
+ /* now want f0 + 6144*f1 + ... as a 64-bit integer */
+ f1 *= 3;
+ f2 *= 9;
+ f3 *= 27;
+ f4 *= 81;
+ /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */
+ f0 += f1 << 11;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ f0 += f2 << 6;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ f0 += f3 << 1;
+ *c++ = f0; f0 >>= 8;
+ f0 += f4 << 4;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+ }
+ /* XXX: using p mod 5 = 1 */
+ f0 = *f++ + qshift;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+}
+
+static void rq_decode(modq *f,const unsigned char *c)
+{
+ crypto_uint32 c0, c1, c2, c3, c4, c5, c6, c7;
+ crypto_uint32 f0, f1, f2, f3, f4;
+ int i;
+
+ for (i = 0;i < p/5;++i) {
+ c0 = *c++;
+ c1 = *c++;
+ c2 = *c++;
+ c3 = *c++;
+ c4 = *c++;
+ c5 = *c++;
+ c6 = *c++;
+ c7 = *c++;
+
+ /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */
+ /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */
+ /* with each f between 0 and 4590 */
+
+ c6 += c7 << 8;
+ /* c6 <= 23241 = floor(4591*6144^4/2^48) */
+ /* f4 = (16/81)c6 + (1/1296)(c5+[0,1]) - [0,0.75] */
+ /* claim: 2^19 f4 < x < 2^19(f4+1) */
+ /* where x = 103564 c6 + 405(c5+1) */
+ /* proof: x - 2^19 f4 = (76/81)c6 + (37/81)c5 + 405 - (32768/81)[0,1] + 2^19[0,0.75] */
+ /* at least 405 - 32768/81 > 0 */
+ /* at most (76/81)23241 + (37/81)255 + 405 + 2^19 0.75 < 2^19 */
+ f4 = (103564*c6 + 405*(c5+1)) >> 19;
+
+ c5 += c6 << 8;
+ c5 -= (f4 * 81) << 4;
+ c4 += c5 << 8;
+
+ /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 */
+ /* = c0 + c1*256 + c2*256^2 + c3*256^3 + c4*256^4 */
+ /* c4 <= 247914 = floor(4591*6144^3/2^32) */
+ /* f3 = (1/54)(c4+[0,1]) - [0,0.75] */
+ /* claim: 2^19 f3 < x < 2^19(f3+1) */
+ /* where x = 9709(c4+2) */
+ /* proof: x - 2^19 f3 = 19418 - (1/27)c4 - (262144/27)[0,1] + 2^19[0,0.75] */
+ /* at least 19418 - 247914/27 - 262144/27 > 0 */
+ /* at most 19418 + 2^19 0.75 < 2^19 */
+ f3 = (9709*(c4+2)) >> 19;
+
+ c4 -= (f3 * 27) << 1;
+ c3 += c4 << 8;
+ /* f0 + f1*6144 + f2*6144^2 */
+ /* = c0 + c1*256 + c2*256^2 + c3*256^3 */
+ /* c3 <= 10329 = floor(4591*6144^2/2^24) */
+ /* f2 = (4/9)c3 + (1/576)c2 + (1/147456)c1 + (1/37748736)c0 - [0,0.75] */
+ /* claim: 2^19 f2 < x < 2^19(f2+1) */
+ /* where x = 233017 c3 + 910(c2+2) */
+ /* proof: x - 2^19 f2 = 1820 + (1/9)c3 - (2/9)c2 - (32/9)c1 - (1/72)c0 + 2^19[0,0.75] */
+ /* at least 1820 - (2/9)255 - (32/9)255 - (1/72)255 > 0 */
+ /* at most 1820 + (1/9)10329 + 2^19 0.75 < 2^19 */
+ f2 = (233017*c3 + 910*(c2+2)) >> 19;
+
+ c2 += c3 << 8;
+ c2 -= (f2 * 9) << 6;
+ c1 += c2 << 8;
+ /* f0 + f1*6144 */
+ /* = c0 + c1*256 */
+ /* c1 <= 110184 = floor(4591*6144/2^8) */
+ /* f1 = (1/24)c1 + (1/6144)c0 - (1/6144)f0 */
+ /* claim: 2^19 f1 < x < 2^19(f1+1) */
+ /* where x = 21845(c1+2) + 85 c0 */
+ /* proof: x - 2^19 f1 = 43690 - (1/3)c1 - (1/3)c0 + 2^19 [0,0.75] */
+ /* at least 43690 - (1/3)110184 - (1/3)255 > 0 */
+ /* at most 43690 + 2^19 0.75 < 2^19 */
+ f1 = (21845*(c1+2) + 85*c0) >> 19;
+
+ c1 -= (f1 * 3) << 3;
+ c0 += c1 << 8;
+ f0 = c0;
+
+ *f++ = modq_freeze(f0 + q - qshift);
+ *f++ = modq_freeze(f1 + q - qshift);
+ *f++ = modq_freeze(f2 + q - qshift);
+ *f++ = modq_freeze(f3 + q - qshift);
+ *f++ = modq_freeze(f4 + q - qshift);
+ }
+
+ c0 = *c++;
+ c1 = *c++;
+ c0 += c1 << 8;
+ *f++ = modq_freeze(c0 + q - qshift);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_mult.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_mult(modq *h,const modq *f,const small *g)
+{
+ modq fg[p + p - 1];
+ modq result;
+ int i, j;
+
+ for (i = 0;i < p;++i) {
+ result = 0;
+ for (j = 0;j <= i;++j)
+ result = modq_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+ for (i = p;i < p + p - 1;++i) {
+ result = 0;
+ for (j = i - p + 1;j < p;++j)
+ result = modq_plusproduct(result,f[j],g[i - j]);
+ fg[i] = result;
+ }
+
+ for (i = p + p - 2;i >= p;--i) {
+ fg[i - p] = modq_sum(fg[i - p],fg[i]);
+ fg[i - p + 1] = modq_sum(fg[i - p + 1],fg[i]);
+ }
+
+ for (i = 0;i < p;++i)
+ h[i] = fg[i];
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_recip3.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+/* caller must ensure that x-y does not overflow */
+static int smaller_mask_rq_recip3(int x,int y)
+{
+ return (x - y) >> 31;
+}
+
+static void vectormodq_product(modq *z,int len,const modq *x,const modq c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = modq_product(x[i],c);
+}
+
+static void vectormodq_minusproduct(modq *z,int len,const modq *x,const modq *y,const modq c)
+{
+ int i;
+ for (i = 0;i < len;++i) z[i] = modq_minusproduct(x[i],y[i],c);
+}
+
+static void vectormodq_shift(modq *z,int len)
+{
+ int i;
+ for (i = len - 1;i > 0;--i) z[i] = z[i - 1];
+ z[0] = 0;
+}
+
+/*
+r = (3s)^(-1) mod m, returning 0, if s is invertible mod m
+or returning -1 if s is not invertible mod m
+r,s are polys of degree <p
+m is x^p-x-1
+*/
+int rq_recip3(modq *r,const small *s)
+{
+ const int loops = 2*p + 1;
+ int loop;
+ modq f[p + 1];
+ modq g[p + 1];
+ modq u[2*p + 2];
+ modq v[2*p + 2];
+ modq c;
+ int i;
+ int d = p;
+ int e = p;
+ int swapmask;
+
+ for (i = 2;i < p;++i) f[i] = 0;
+ f[0] = -1;
+ f[1] = -1;
+ f[p] = 1;
+ /* generalization: can initialize f to any polynomial m */
+ /* requirements: m has degree exactly p, nonzero constant coefficient */
+
+ for (i = 0;i < p;++i) g[i] = 3 * s[i];
+ g[p] = 0;
+
+ for (i = 0;i <= loops;++i) u[i] = 0;
+
+ v[0] = 1;
+ for (i = 1;i <= loops;++i) v[i] = 0;
+
+ loop = 0;
+ for (;;) {
+ /* e == -1 or d + e + loop <= 2*p */
+
+ /* f has degree p: i.e., f[p]!=0 */
+ /* f[i]==0 for i < p-d */
+
+ /* g has degree <=p (so it fits in p+1 coefficients) */
+ /* g[i]==0 for i < p-e */
+
+ /* u has degree <=loop (so it fits in loop+1 coefficients) */
+ /* u[i]==0 for i < p-d */
+ /* if invertible: u[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ /* v has degree <=loop (so it fits in loop+1 coefficients) */
+ /* v[i]==0 for i < p-e */
+ /* v[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
+
+ if (loop >= loops) break;
+
+ c = modq_quotient(g[p],f[p]);
+
+ vectormodq_minusproduct(g,p + 1,g,f,c);
+ vectormodq_shift(g,p + 1);
+
+#ifdef SIMPLER
+ vectormodq_minusproduct(v,loops + 1,v,u,c);
+ vectormodq_shift(v,loops + 1);
+#else
+ if (loop < p) {
+ vectormodq_minusproduct(v,loop + 1,v,u,c);
+ vectormodq_shift(v,loop + 2);
+ } else {
+ vectormodq_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c);
+ vectormodq_shift(v + loop - p,p + 2);
+ }
+#endif
+
+ e -= 1;
+
+ ++loop;
+
+ swapmask = smaller_mask_rq_recip3(e,d) & modq_nonzero_mask(g[p]);
+ swap(&e,&d,sizeof e,swapmask);
+ swap(f,g,(p + 1) * sizeof(modq),swapmask);
+
+#ifdef SIMPLER
+ swap(u,v,(loops + 1) * sizeof(modq),swapmask);
+#else
+ if (loop < p) {
+ swap(u,v,(loop + 1) * sizeof(modq),swapmask);
+ } else {
+ swap(u + loop - p,v + loop - p,(p + 1) * sizeof(modq),swapmask);
+ }
+#endif
+ }
+
+ c = modq_reciprocal(f[p]);
+ vectormodq_product(r,p,u + p,c);
+ return smaller_mask_rq_recip3(0,d);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_round3.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_round3(modq *h,const modq *f)
+{
+ int i;
+
+ for (i = 0;i < p;++i)
+ h[i] = ((21846 * (f[i] + 2295) + 32768) >> 16) * 3 - 2295;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_rounded.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void rq_encoderounded(unsigned char *c,const modq *f)
+{
+ crypto_int32 f0, f1, f2;
+ int i;
+
+ for (i = 0;i < p/3;++i) {
+ f0 = *f++ + qshift;
+ f1 = *f++ + qshift;
+ f2 = *f++ + qshift;
+ f0 = (21846 * f0) >> 16;
+ f1 = (21846 * f1) >> 16;
+ f2 = (21846 * f2) >> 16;
+ /* now want f0 + f1*1536 + f2*1536^2 as a 32-bit integer */
+ f2 *= 3;
+ f1 += f2 << 9;
+ f1 *= 3;
+ f0 += f1 << 9;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+ }
+ /* XXX: using p mod 3 = 2 */
+ f0 = *f++ + qshift;
+ f1 = *f++ + qshift;
+ f0 = (21846 * f0) >> 16;
+ f1 = (21846 * f1) >> 16;
+ f1 *= 3;
+ f0 += f1 << 9;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0; f0 >>= 8;
+ *c++ = f0;
+}
+
+static void rq_decoderounded(modq *f,const unsigned char *c)
+{
+ crypto_uint32 c0, c1, c2, c3;
+ crypto_uint32 f0, f1, f2;
+ int i;
+
+ for (i = 0;i < p/3;++i) {
+ c0 = *c++;
+ c1 = *c++;
+ c2 = *c++;
+ c3 = *c++;
+
+ /* f0 + f1*1536 + f2*1536^2 */
+ /* = c0 + c1*256 + c2*256^2 + c3*256^3 */
+ /* with each f between 0 and 1530 */
+
+ /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */
+ /* claim: 2^21 f2 < x < 2^21(f2+1) */
+ /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */
+ /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 [0,0.99675] */
+ /* at least 456 - (8/9)255 - (2/9)255 > 0 */
+ /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */
+ f2 = (14913081*c3 + 58254*c2 + 228*(c1+2)) >> 21;
+
+ c2 += c3 << 8;
+ c2 -= (f2 * 9) << 2;
+ /* f0 + f1*1536 */
+ /* = c0 + c1*256 + c2*256^2 */
+ /* c2 <= 35 = floor((1530+1530*1536)/256^2) */
+ /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */
+ /* claim: 2^21 f1 < x < 2^21(f1+1) */
+ /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */
+ /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */
+ /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */
+ /* at most 1365 + (4096/3)1530 < 2^21 */
+ f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21;
+
+ c1 += c2 << 8;
+ c1 -= (f1 * 3) << 1;
+
+ c0 += c1 << 8;
+ f0 = c0;
+
+ *f++ = modq_freeze(f0 * 3 + q - qshift);
+ *f++ = modq_freeze(f1 * 3 + q - qshift);
+ *f++ = modq_freeze(f2 * 3 + q - qshift);
+ }
+
+ c0 = *c++;
+ c1 = *c++;
+ c2 = *c++;
+
+ f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21;
+
+ c1 += c2 << 8;
+ c1 -= (f1 * 3) << 1;
+
+ c0 += c1 << 8;
+ f0 = c0;
+
+ *f++ = modq_freeze(f0 * 3 + q - qshift);
+ *f++ = modq_freeze(f1 * 3 + q - qshift);
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+/* XXX: these functions rely on p mod 4 = 1 */
+
+/* all coefficients in -1, 0, 1 */
+static void small_encode(unsigned char *c,const small *f)
+{
+ small c0;
+ int i;
+
+ for (i = 0;i < p/4;++i) {
+ c0 = *f++ + 1;
+ c0 += (*f++ + 1) << 2;
+ c0 += (*f++ + 1) << 4;
+ c0 += (*f++ + 1) << 6;
+ *c++ = c0;
+ }
+ c0 = *f++ + 1;
+ *c++ = c0;
+}
+
+static void small_decode(small *f,const unsigned char *c)
+{
+ unsigned char c0;
+ int i;
+
+ for (i = 0;i < p/4;++i) {
+ c0 = *c++;
+ *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
+ *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
+ *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
+ *f++ = ((small) (c0 & 3)) - 1;
+ }
+ c0 = *c++;
+ *f++ = ((small) (c0 & 3)) - 1;
+}
+
+/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.c */
+/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
+
+
+static void swap(void *x,void *y,int bytes,int mask)
+{
+ int i;
+ char xi, yi, c, t;
+
+ c = mask;
+
+ for (i = 0;i < bytes;++i) {
+ xi = i[(char *) x];
+ yi = i[(char *) y];
+ t = c & (xi ^ yi);
+ xi ^= t;
+ yi ^= t;
+ i[(char *) x] = xi;
+ i[(char *) y] = yi;
+ }
+}
+
diff --git a/sntrup4591761.sh b/sntrup4591761.sh
new file mode 100644
index 000000000000..e684c3329c2e
--- /dev/null
+++ b/sntrup4591761.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# $OpenBSD: sntrup4591761.sh,v 1.3 2019/01/30 19:51:15 markus Exp $
+# Placed in the Public Domain.
+#
+AUTHOR="libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/implementors"
+FILES="
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/mod3.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/modq.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/params.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.h
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/dec.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/enc.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/keypair.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_mult.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_recip.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomsmall.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomweightw.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_mult.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_recip3.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_round3.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_rounded.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.c
+ libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.c
+"
+###
+
+set -e
+cd $1
+echo -n '/* $'
+echo 'OpenBSD: $ */'
+echo
+echo '/*'
+echo ' * Public Domain, Authors:'
+sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR
+echo ' */'
+echo
+echo '#include <string.h>'
+echo '#include "crypto_api.h"'
+echo
+for i in $FILES; do
+ echo "/* from $i */"
+ b=$(basename $i .c)
+ grep \
+ -v '#include' $i | \
+ grep -v "extern crypto_int32 small_random32" |
+ sed -e "s/crypto_kem_/crypto_kem_sntrup4591761_/g" \
+ -e "s/smaller_mask/smaller_mask_${b}/g" \
+ -e "s/^extern void /static void /" \
+ -e "s/^void /static void /"
+ echo
+done
diff --git a/ssh-add.0 b/ssh-add.0
index d60ae715ee94..c614a2fe5c42 100644
--- a/ssh-add.0
+++ b/ssh-add.0
@@ -1,123 +1,133 @@
SSH-ADD(1) General Commands Manual SSH-ADD(1)
NAME
ssh-add M-bM-^@M-^S adds private key identities to the authentication agent
SYNOPSIS
- ssh-add [-cDdkLlqXx] [-E fingerprint_hash] [-t life] [file ...]
+ ssh-add [-cDdkLlqvXx] [-E fingerprint_hash] [-t life] [file ...]
ssh-add -s pkcs11
ssh-add -e pkcs11
+ ssh-add -T pubkey ...
DESCRIPTION
ssh-add adds private key identities to the authentication agent,
ssh-agent(1). When run without arguments, it adds the files
~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, and ~/.ssh/id_ed25519.
After loading a private key, ssh-add will try to load corresponding
certificate information from the filename obtained by appending -cert.pub
to the name of the private key file. Alternative file names can be given
on the command line.
If any file requires a passphrase, ssh-add asks for the passphrase from
the user. The passphrase is read from the user's tty. ssh-add retries
the last passphrase if multiple identity files are given.
The authentication agent must be running and the SSH_AUTH_SOCK
environment variable must contain the name of its socket for ssh-add to
work.
The options are as follows:
-c Indicates that added identities should be subject to confirmation
before being used for authentication. Confirmation is performed
by ssh-askpass(1). Successful confirmation is signaled by a zero
exit status from ssh-askpass(1), rather than text entered into
the requester.
-D Deletes all identities from the agent.
-d Instead of adding identities, removes identities from the agent.
If ssh-add has been run without arguments, the keys for the
default identities and their corresponding certificates will be
removed. Otherwise, the argument list will be interpreted as a
list of paths to public key files to specify keys and
certificates to be removed from the agent. If no public key is
found at a given path, ssh-add will append .pub and retry.
-E fingerprint_hash
Specifies the hash algorithm used when displaying key
fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
default is M-bM-^@M-^\sha256M-bM-^@M-^].
-e pkcs11
Remove keys provided by the PKCS#11 shared library pkcs11.
-k When loading keys into or deleting keys from the agent, process
plain private keys only and skip certificates.
-L Lists public key parameters of all identities currently
represented by the agent.
-l Lists fingerprints of all identities currently represented by the
agent.
-q Be quiet after a successful operation.
-s pkcs11
Add keys provided by the PKCS#11 shared library pkcs11.
+ -T pubkey ...
+ Tests whether the private keys that correspond to the specified
+ pubkey files are usable by performing sign and verify operations
+ on each.
+
-t life
Set a maximum lifetime when adding identities to an agent. The
lifetime may be specified in seconds or in a time format
specified in sshd_config(5).
+ -v Verbose mode. Causes ssh-add to print debugging messages about
+ its progress. This is helpful in debugging problems. Multiple
+ -v options increase the verbosity. The maximum is 3.
+
-X Unlock the agent.
-x Lock the agent with a password.
ENVIRONMENT
DISPLAY and SSH_ASKPASS
If ssh-add needs a passphrase, it will read the passphrase from
the current terminal if it was run from a terminal. If ssh-add
does not have a terminal associated with it but DISPLAY and
SSH_ASKPASS are set, it will execute the program specified by
SSH_ASKPASS (by default M-bM-^@M-^\ssh-askpassM-bM-^@M-^]) and open an X11 window to
read the passphrase. This is particularly useful when calling
ssh-add from a .xsession or related script. (Note that on some
machines it may be necessary to redirect the input from /dev/null
to make this work.)
SSH_AUTH_SOCK
Identifies the path of a UNIX-domain socket used to communicate
with the agent.
FILES
~/.ssh/id_dsa
Contains the DSA authentication identity of the user.
~/.ssh/id_ecdsa
Contains the ECDSA authentication identity of the user.
~/.ssh/id_ed25519
Contains the Ed25519 authentication identity of the user.
~/.ssh/id_rsa
Contains the RSA authentication identity of the user.
Identity files should not be readable by anyone but the user. Note that
ssh-add ignores identity files if they are accessible by others.
EXIT STATUS
Exit status is 0 on success, 1 if the specified command fails, and 2 if
ssh-add is unable to contact the authentication agent.
SEE ALSO
ssh(1), ssh-agent(1), ssh-askpass(1), ssh-keygen(1), sshd(8)
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
-OpenBSD 6.4 August 29, 2017 OpenBSD 6.4
+OpenBSD 6.5 January 21, 2019 OpenBSD 6.5
diff --git a/ssh-add.1 b/ssh-add.1
index d5da9279c5f9..d4e1c603be6d 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,211 +1,228 @@
-.\" $OpenBSD: ssh-add.1,v 1.66 2017/08/29 13:05:58 jmc Exp $
+.\" $OpenBSD: ssh-add.1,v 1.69 2019/01/21 12:53:35 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" As far as I am concerned, the code I have written for this software
.\" can be used freely for any purpose. Any derived versions of this
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: August 29 2017 $
+.Dd $Mdocdate: January 21 2019 $
.Dt SSH-ADD 1
.Os
.Sh NAME
.Nm ssh-add
.Nd adds private key identities to the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
-.Op Fl cDdkLlqXx
+.Op Fl cDdkLlqvXx
.Op Fl E Ar fingerprint_hash
.Op Fl t Ar life
.Op Ar
.Nm ssh-add
.Fl s Ar pkcs11
.Nm ssh-add
.Fl e Ar pkcs11
+.Nm ssh-add
+.Fl T
+.Ar pubkey ...
.Sh DESCRIPTION
.Nm
adds private key identities to the authentication agent,
.Xr ssh-agent 1 .
When run without arguments, it adds the files
.Pa ~/.ssh/id_rsa ,
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
and
.Pa ~/.ssh/id_ed25519 .
After loading a private key,
.Nm
will try to load corresponding certificate information from the
filename obtained by appending
.Pa -cert.pub
to the name of the private key file.
Alternative file names can be given on the command line.
.Pp
If any file requires a passphrase,
.Nm
asks for the passphrase from the user.
The passphrase is read from the user's tty.
.Nm
retries the last passphrase if multiple identity files are given.
.Pp
The authentication agent must be running and the
.Ev SSH_AUTH_SOCK
environment variable must contain the name of its socket for
.Nm
to work.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl c
Indicates that added identities should be subject to confirmation before
being used for authentication.
Confirmation is performed by
.Xr ssh-askpass 1 .
Successful confirmation is signaled by a zero exit status from
.Xr ssh-askpass 1 ,
rather than text entered into the requester.
.It Fl D
Deletes all identities from the agent.
.It Fl d
Instead of adding identities, removes identities from the agent.
If
.Nm
has been run without arguments, the keys for the default identities and
their corresponding certificates will be removed.
Otherwise, the argument list will be interpreted as a list of paths to
public key files to specify keys and certificates to be removed from the agent.
If no public key is found at a given path,
.Nm
will append
.Pa .pub
and retry.
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
.Dq sha256 .
.It Fl e Ar pkcs11
Remove keys provided by the PKCS#11 shared library
.Ar pkcs11 .
.It Fl k
When loading keys into or deleting keys from the agent, process plain private
keys only and skip certificates.
.It Fl L
Lists public key parameters of all identities currently represented
by the agent.
.It Fl l
Lists fingerprints of all identities currently represented by the agent.
.It Fl q
Be quiet after a successful operation.
.It Fl s Ar pkcs11
Add keys provided by the PKCS#11 shared library
.Ar pkcs11 .
+.It Fl T Ar pubkey ...
+Tests whether the private keys that correspond to the specified
+.Ar pubkey
+files are usable by performing sign and verify operations on each.
.It Fl t Ar life
Set a maximum lifetime when adding identities to an agent.
The lifetime may be specified in seconds or in a time format
specified in
.Xr sshd_config 5 .
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in debugging problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
.It Fl X
Unlock the agent.
.It Fl x
Lock the agent with a password.
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev "DISPLAY" and "SSH_ASKPASS"
If
.Nm
needs a passphrase, it will read the passphrase from the current
terminal if it was run from a terminal.
If
.Nm
does not have a terminal associated with it but
.Ev DISPLAY
and
.Ev SSH_ASKPASS
are set, it will execute the program specified by
.Ev SSH_ASKPASS
(by default
.Dq ssh-askpass )
and open an X11 window to read the passphrase.
This is particularly useful when calling
.Nm
from a
.Pa .xsession
or related script.
(Note that on some machines it
may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
.It Ev SSH_AUTH_SOCK
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
.El
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/id_dsa
Contains the DSA authentication identity of the user.
.It Pa ~/.ssh/id_ecdsa
Contains the ECDSA authentication identity of the user.
.It Pa ~/.ssh/id_ed25519
Contains the Ed25519 authentication identity of the user.
.It Pa ~/.ssh/id_rsa
Contains the RSA authentication identity of the user.
.El
.Pp
Identity files should not be readable by anyone but the user.
Note that
.Nm
ignores identity files if they are accessible by others.
.Sh EXIT STATUS
Exit status is 0 on success, 1 if the specified command fails,
and 2 if
.Nm
is unable to contact the authentication agent.
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-askpass 1 ,
.Xr ssh-keygen 1 ,
.Xr sshd 8
.Sh AUTHORS
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by Tatu Ylonen.
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
Theo de Raadt and Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
diff --git a/ssh-add.c b/ssh-add.c
index 627c02983685..ac9c808dd2de 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,699 +1,753 @@
-/* $OpenBSD: ssh-add.c,v 1.136 2018/09/19 02:03:02 djm Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.138 2019/01/21 12:53:35 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Adds an identity to the authentication server, or removes an identity.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation,
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <openssl/evp.h>
#include "openbsd-compat/openssl-compat.h"
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "xmalloc.h"
#include "ssh.h"
#include "log.h"
#include "sshkey.h"
#include "sshbuf.h"
#include "authfd.h"
#include "authfile.h"
#include "pathnames.h"
#include "misc.h"
#include "ssherr.h"
#include "digest.h"
/* argv0 */
extern char *__progname;
/* Default files to add */
static char *default_files[] = {
#ifdef WITH_OPENSSL
_PATH_SSH_CLIENT_ID_RSA,
_PATH_SSH_CLIENT_ID_DSA,
#ifdef OPENSSL_HAS_ECC
_PATH_SSH_CLIENT_ID_ECDSA,
#endif
#endif /* WITH_OPENSSL */
_PATH_SSH_CLIENT_ID_ED25519,
_PATH_SSH_CLIENT_ID_XMSS,
NULL
};
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* Default lifetime (0 == forever) */
static int lifetime = 0;
/* User has to confirm key use */
static int confirm = 0;
/* Maximum number of signatures (XMSS) */
static u_int maxsign = 0;
static u_int minleft = 0;
/* we keep a cache of one passphrase */
static char *pass = NULL;
static void
clear_pass(void)
{
if (pass) {
explicit_bzero(pass, strlen(pass));
free(pass);
pass = NULL;
}
}
static int
delete_file(int agent_fd, const char *filename, int key_only, int qflag)
{
struct sshkey *public, *cert = NULL;
char *certpath = NULL, *comment = NULL;
int r, ret = -1;
if ((r = sshkey_load_public(filename, &public, &comment)) != 0) {
printf("Bad key file %s: %s\n", filename, ssh_err(r));
return -1;
}
if ((r = ssh_remove_identity(agent_fd, public)) == 0) {
if (!qflag) {
fprintf(stderr, "Identity removed: %s (%s)\n",
filename, comment);
}
ret = 0;
} else
fprintf(stderr, "Could not remove identity \"%s\": %s\n",
filename, ssh_err(r));
if (key_only)
goto out;
/* Now try to delete the corresponding certificate too */
free(comment);
comment = NULL;
xasprintf(&certpath, "%s-cert.pub", filename);
if ((r = sshkey_load_public(certpath, &cert, &comment)) != 0) {
if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
error("Failed to load certificate \"%s\": %s",
certpath, ssh_err(r));
goto out;
}
if (!sshkey_equal_public(cert, public))
fatal("Certificate %s does not match private key %s",
certpath, filename);
if ((r = ssh_remove_identity(agent_fd, cert)) == 0) {
if (!qflag) {
fprintf(stderr, "Identity removed: %s (%s)\n",
certpath, comment);
}
ret = 0;
} else
fprintf(stderr, "Could not remove identity \"%s\": %s\n",
certpath, ssh_err(r));
out:
sshkey_free(cert);
sshkey_free(public);
free(certpath);
free(comment);
return ret;
}
/* Send a request to remove all identities. */
static int
delete_all(int agent_fd, int qflag)
{
int ret = -1;
/*
* Since the agent might be forwarded, old or non-OpenSSH, when asked
* to remove all keys, attempt to remove both protocol v.1 and v.2
* keys.
*/
if (ssh_remove_all_identities(agent_fd, 2) == 0)
ret = 0;
/* ignore error-code for ssh1 */
ssh_remove_all_identities(agent_fd, 1);
if (ret != 0)
fprintf(stderr, "Failed to remove all identities.\n");
else if (!qflag)
fprintf(stderr, "All identities removed.\n");
return ret;
}
static int
add_file(int agent_fd, const char *filename, int key_only, int qflag)
{
struct sshkey *private, *cert;
char *comment = NULL;
char msg[1024], *certpath = NULL;
int r, fd, ret = -1;
size_t i;
u_int32_t left;
struct sshbuf *keyblob;
struct ssh_identitylist *idlist;
if (strcmp(filename, "-") == 0) {
fd = STDIN_FILENO;
filename = "(stdin)";
} else if ((fd = open(filename, O_RDONLY)) < 0) {
perror(filename);
return -1;
}
/*
* Since we'll try to load a keyfile multiple times, permission errors
* will occur multiple times, so check perms first and bail if wrong.
*/
if (fd != STDIN_FILENO) {
if (sshkey_perm_ok(fd, filename) != 0) {
close(fd);
return -1;
}
}
if ((keyblob = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshkey_load_file(fd, keyblob)) != 0) {
fprintf(stderr, "Error loading key \"%s\": %s\n",
filename, ssh_err(r));
sshbuf_free(keyblob);
close(fd);
return -1;
}
close(fd);
/* At first, try empty passphrase */
if ((r = sshkey_parse_private_fileblob(keyblob, "", &private,
&comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
fprintf(stderr, "Error loading key \"%s\": %s\n",
filename, ssh_err(r));
goto fail_load;
}
/* try last */
if (private == NULL && pass != NULL) {
if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private,
&comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
fprintf(stderr, "Error loading key \"%s\": %s\n",
filename, ssh_err(r));
goto fail_load;
}
}
if (private == NULL) {
/* clear passphrase since it did not work */
clear_pass();
snprintf(msg, sizeof msg, "Enter passphrase for %s%s: ",
filename, confirm ? " (will confirm each use)" : "");
for (;;) {
pass = read_passphrase(msg, RP_ALLOW_STDIN);
if (strcmp(pass, "") == 0)
goto fail_load;
if ((r = sshkey_parse_private_fileblob(keyblob, pass,
&private, &comment)) == 0)
break;
else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
fprintf(stderr,
"Error loading key \"%s\": %s\n",
filename, ssh_err(r));
fail_load:
clear_pass();
sshbuf_free(keyblob);
return -1;
}
clear_pass();
snprintf(msg, sizeof msg,
"Bad passphrase, try again for %s%s: ", filename,
confirm ? " (will confirm each use)" : "");
}
}
if (comment == NULL || *comment == '\0')
comment = xstrdup(filename);
sshbuf_free(keyblob);
/* For XMSS */
if ((r = sshkey_set_filename(private, filename)) != 0) {
fprintf(stderr, "Could not add filename to private key: %s (%s)\n",
filename, comment);
goto out;
}
if (maxsign && minleft &&
(r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) {
for (i = 0; i < idlist->nkeys; i++) {
if (!sshkey_equal_public(idlist->keys[i], private))
continue;
left = sshkey_signatures_left(idlist->keys[i]);
if (left < minleft) {
fprintf(stderr,
"Only %d signatures left.\n", left);
break;
}
fprintf(stderr, "Skipping update: ");
if (left == minleft) {
fprintf(stderr,
"required signatures left (%d).\n", left);
} else {
fprintf(stderr,
"more signatures left (%d) than"
" required (%d).\n", left, minleft);
}
ssh_free_identitylist(idlist);
goto out;
}
ssh_free_identitylist(idlist);
}
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
lifetime, confirm, maxsign)) == 0) {
ret = 0;
if (!qflag) {
fprintf(stderr, "Identity added: %s (%s)\n",
filename, comment);
if (lifetime != 0) {
fprintf(stderr,
"Lifetime set to %d seconds\n", lifetime);
}
if (confirm != 0) {
fprintf(stderr, "The user must confirm "
"each use of the key\n");
}
}
} else {
fprintf(stderr, "Could not add identity \"%s\": %s\n",
filename, ssh_err(r));
}
/* Skip trying to load the cert if requested */
if (key_only)
goto out;
/* Now try to add the certificate flavour too */
xasprintf(&certpath, "%s-cert.pub", filename);
if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
error("Failed to load certificate \"%s\": %s",
certpath, ssh_err(r));
goto out;
}
if (!sshkey_equal_public(cert, private)) {
error("Certificate %s does not match private key %s",
certpath, filename);
sshkey_free(cert);
goto out;
}
/* Graft with private bits */
if ((r = sshkey_to_certified(private)) != 0) {
error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
sshkey_free(cert);
goto out;
}
if ((r = sshkey_cert_copy(cert, private)) != 0) {
error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
sshkey_free(cert);
goto out;
}
sshkey_free(cert);
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
lifetime, confirm, maxsign)) != 0) {
error("Certificate %s (%s) add failed: %s", certpath,
private->cert->key_id, ssh_err(r));
goto out;
}
/* success */
if (!qflag) {
fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
private->cert->key_id);
if (lifetime != 0) {
fprintf(stderr, "Lifetime set to %d seconds\n",
lifetime);
}
if (confirm != 0) {
fprintf(stderr, "The user must confirm each use "
"of the key\n");
}
}
out:
free(certpath);
free(comment);
sshkey_free(private);
return ret;
}
static int
update_card(int agent_fd, int add, const char *id, int qflag)
{
char *pin = NULL;
int r, ret = -1;
if (add) {
if ((pin = read_passphrase("Enter passphrase for PKCS#11: ",
RP_ALLOW_STDIN)) == NULL)
return -1;
}
if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin,
lifetime, confirm)) == 0) {
ret = 0;
if (!qflag) {
fprintf(stderr, "Card %s: %s\n",
add ? "added" : "removed", id);
}
} else {
fprintf(stderr, "Could not %s card \"%s\": %s\n",
add ? "add" : "remove", id, ssh_err(r));
ret = -1;
}
free(pin);
return ret;
}
+static int
+test_key(int agent_fd, const char *filename)
+{
+ struct sshkey *key = NULL;
+ u_char *sig = NULL;
+ size_t slen = 0;
+ int r, ret = -1;
+ char data[1024];
+
+ if ((r = sshkey_load_public(filename, &key, NULL)) != 0) {
+ error("Couldn't read public key %s: %s", filename, ssh_err(r));
+ return -1;
+ }
+ arc4random_buf(data, sizeof(data));
+ if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data),
+ NULL, 0)) != 0) {
+ error("Agent signature failed for %s: %s",
+ filename, ssh_err(r));
+ goto done;
+ }
+ if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
+ NULL, 0)) != 0) {
+ error("Signature verification failed for %s: %s",
+ filename, ssh_err(r));
+ goto done;
+ }
+ /* success */
+ ret = 0;
+ done:
+ free(sig);
+ sshkey_free(key);
+ return ret;
+}
+
static int
list_identities(int agent_fd, int do_fp)
{
char *fp;
int r;
struct ssh_identitylist *idlist;
u_int32_t left;
size_t i;
if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
fprintf(stderr, "error fetching identities: %s\n",
ssh_err(r));
else
printf("The agent has no identities.\n");
return -1;
}
for (i = 0; i < idlist->nkeys; i++) {
if (do_fp) {
fp = sshkey_fingerprint(idlist->keys[i],
fingerprint_hash, SSH_FP_DEFAULT);
printf("%u %s %s (%s)\n", sshkey_size(idlist->keys[i]),
fp == NULL ? "(null)" : fp, idlist->comments[i],
sshkey_type(idlist->keys[i]));
free(fp);
} else {
if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) {
fprintf(stderr, "sshkey_write: %s\n",
ssh_err(r));
continue;
}
fprintf(stdout, " %s", idlist->comments[i]);
left = sshkey_signatures_left(idlist->keys[i]);
if (left > 0)
fprintf(stdout,
" [signatures left %d]", left);
fprintf(stdout, "\n");
}
}
ssh_free_identitylist(idlist);
return 0;
}
static int
lock_agent(int agent_fd, int lock)
{
char prompt[100], *p1, *p2;
int r, passok = 1, ret = -1;
strlcpy(prompt, "Enter lock password: ", sizeof(prompt));
p1 = read_passphrase(prompt, RP_ALLOW_STDIN);
if (lock) {
strlcpy(prompt, "Again: ", sizeof prompt);
p2 = read_passphrase(prompt, RP_ALLOW_STDIN);
if (strcmp(p1, p2) != 0) {
fprintf(stderr, "Passwords do not match.\n");
passok = 0;
}
explicit_bzero(p2, strlen(p2));
free(p2);
}
if (passok) {
if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) {
fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un");
ret = 0;
} else {
fprintf(stderr, "Failed to %slock agent: %s\n",
lock ? "" : "un", ssh_err(r));
}
}
explicit_bzero(p1, strlen(p1));
free(p1);
return (ret);
}
static int
do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)
{
if (deleting) {
if (delete_file(agent_fd, file, key_only, qflag) == -1)
return -1;
} else {
if (add_file(agent_fd, file, key_only, qflag) == -1)
return -1;
}
return 0;
}
static void
usage(void)
{
fprintf(stderr, "usage: %s [options] [file ...]\n", __progname);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -l List fingerprints of all identities.\n");
fprintf(stderr, " -E hash Specify hash algorithm used for fingerprints.\n");
fprintf(stderr, " -L List public key parameters of all identities.\n");
fprintf(stderr, " -k Load only keys and not certificates.\n");
fprintf(stderr, " -c Require confirmation to sign using identities\n");
fprintf(stderr, " -m minleft Maxsign is only changed if less than minleft are left (for XMSS)\n");
fprintf(stderr, " -M maxsign Maximum number of signatures allowed (for XMSS)\n");
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
fprintf(stderr, " -d Delete identity.\n");
fprintf(stderr, " -D Delete all identities.\n");
fprintf(stderr, " -x Lock agent.\n");
fprintf(stderr, " -X Unlock agent.\n");
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
+ fprintf(stderr, " -T pubkey Test if ssh-agent can access matching private key.\n");
fprintf(stderr, " -q Be quiet after a successful operation.\n");
+ fprintf(stderr, " -v Be more verbose.\n");
}
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
int agent_fd;
char *pkcs11provider = NULL;
int r, i, ch, deleting = 0, ret = 0, key_only = 0;
- int xflag = 0, lflag = 0, Dflag = 0, qflag = 0;
+ int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
+ SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
+ LogLevel log_level = SYSLOG_LEVEL_INFO;
ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
__progname = ssh_get_progname(argv[0]);
seed_rng();
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
+ log_init(__progname, log_level, log_facility, 1);
setvbuf(stdout, NULL, _IOLBF, 0);
/* First, get a connection to the authentication agent. */
switch (r = ssh_get_authentication_socket(&agent_fd)) {
case 0:
break;
case SSH_ERR_AGENT_NOT_PRESENT:
fprintf(stderr, "Could not open a connection to your "
"authentication agent.\n");
exit(2);
default:
fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r));
exit(2);
}
- while ((ch = getopt(argc, argv, "klLcdDxXE:e:M:m:qs:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:t:")) != -1) {
switch (ch) {
+ case 'v':
+ if (log_level == SYSLOG_LEVEL_INFO)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
+ break;
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
fatal("Invalid hash algorithm \"%s\"", optarg);
break;
case 'k':
key_only = 1;
break;
case 'l':
case 'L':
if (lflag != 0)
fatal("-%c flag already specified", lflag);
lflag = ch;
break;
case 'x':
case 'X':
if (xflag != 0)
fatal("-%c flag already specified", xflag);
xflag = ch;
break;
case 'c':
confirm = 1;
break;
case 'm':
minleft = (int)strtonum(optarg, 1, UINT_MAX, NULL);
if (minleft == 0) {
usage();
ret = 1;
goto done;
}
break;
case 'M':
maxsign = (int)strtonum(optarg, 1, UINT_MAX, NULL);
if (maxsign == 0) {
usage();
ret = 1;
goto done;
}
break;
case 'd':
deleting = 1;
break;
case 'D':
Dflag = 1;
break;
case 's':
pkcs11provider = optarg;
break;
case 'e':
deleting = 1;
pkcs11provider = optarg;
break;
case 't':
if ((lifetime = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid lifetime\n");
ret = 1;
goto done;
}
break;
case 'q':
qflag = 1;
break;
+ case 'T':
+ Tflag = 1;
+ break;
default:
usage();
ret = 1;
goto done;
}
}
+ log_init(__progname, log_level, log_facility, 1);
if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1)
fatal("Invalid combination of actions");
else if (xflag) {
if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1)
ret = 1;
goto done;
} else if (lflag) {
if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1)
ret = 1;
goto done;
} else if (Dflag) {
if (delete_all(agent_fd, qflag) == -1)
ret = 1;
goto done;
}
argc -= optind;
argv += optind;
+ if (Tflag) {
+ if (argc <= 0)
+ fatal("no keys to test");
+ for (r = i = 0; i < argc; i++)
+ r |= test_key(agent_fd, argv[i]);
+ ret = r == 0 ? 0 : 1;
+ goto done;
+ }
if (pkcs11provider != NULL) {
if (update_card(agent_fd, !deleting, pkcs11provider,
qflag) == -1)
ret = 1;
goto done;
}
if (argc == 0) {
char buf[PATH_MAX];
struct passwd *pw;
struct stat st;
int count = 0;
if ((pw = getpwuid(getuid())) == NULL) {
fprintf(stderr, "No user found with uid %u\n",
(u_int)getuid());
ret = 1;
goto done;
}
for (i = 0; default_files[i]; i++) {
snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir,
default_files[i]);
if (stat(buf, &st) < 0)
continue;
if (do_file(agent_fd, deleting, key_only, buf,
qflag) == -1)
ret = 1;
else
count++;
}
if (count == 0)
ret = 1;
} else {
for (i = 0; i < argc; i++) {
if (do_file(agent_fd, deleting, key_only,
argv[i], qflag) == -1)
ret = 1;
}
}
clear_pass();
done:
ssh_close_authentication_socket(agent_fd);
return ret;
}
diff --git a/ssh-agent.0 b/ssh-agent.0
index f4575d01be05..9f140afb5dd7 100644
--- a/ssh-agent.0
+++ b/ssh-agent.0
@@ -1,120 +1,120 @@
SSH-AGENT(1) General Commands Manual SSH-AGENT(1)
NAME
ssh-agent M-bM-^@M-^S authentication agent
SYNOPSIS
ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]
[-P pkcs11_whitelist] [-t life] [command [arg ...]]
ssh-agent [-c | -s] -k
DESCRIPTION
ssh-agent is a program to hold private keys used for public key
authentication (RSA, DSA, ECDSA, Ed25519). ssh-agent is usually started
in the beginning of an X-session or a login session, and all other
windows or programs are started as clients to the ssh-agent program.
Through use of environment variables the agent can be located and
automatically used for authentication when logging in to other machines
using ssh(1).
The agent initially does not have any private keys. Keys are added using
ssh(1) (see AddKeysToAgent in ssh_config(5) for details) or ssh-add(1).
Multiple identities may be stored in ssh-agent concurrently and ssh(1)
will automatically use them if present. ssh-add(1) is also used to
remove keys from ssh-agent and to query the keys that are held in one.
The options are as follows:
-a bind_address
Bind the agent to the UNIX-domain socket bind_address. The
default is $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>.
-c Generate C-shell commands on stdout. This is the default if
SHELL looks like it's a csh style of shell.
-D Foreground mode. When this option is specified ssh-agent will
not fork.
-d Debug mode. When this option is specified ssh-agent will not
fork and will write debug information to standard error.
-E fingerprint_hash
Specifies the hash algorithm used when displaying key
fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
default is M-bM-^@M-^\sha256M-bM-^@M-^].
-k Kill the current agent (given by the SSH_AGENT_PID environment
variable).
-P pkcs11_whitelist
Specify a pattern-list of acceptable paths for PKCS#11 shared
libraries that may be added using the -s option to ssh-add(1).
The default is to allow loading PKCS#11 libraries from
M-bM-^@M-^\/usr/lib/*,/usr/local/lib/*M-bM-^@M-^]. PKCS#11 libraries that do not
match the whitelist will be refused. See PATTERNS in
ssh_config(5) for a description of pattern-list syntax.
-s Generate Bourne shell commands on stdout. This is the default if
SHELL does not look like it's a csh style of shell.
-t life
Set a default value for the maximum lifetime of identities added
to the agent. The lifetime may be specified in seconds or in a
time format specified in sshd_config(5). A lifetime specified
for an identity with ssh-add(1) overrides this value. Without
this option the default maximum lifetime is forever.
If a command line is given, this is executed as a subprocess of the
agent. When the command dies, so does the agent.
The idea is that the agent is run in the user's local PC, laptop, or
terminal. Authentication data need not be stored on any other machine,
and authentication passphrases never go over the network. However, the
connection to the agent is forwarded over SSH remote logins, and the user
can thus use the privileges given by the identities anywhere in the
network in a secure way.
There are two main ways to get an agent set up: The first is that the
agent starts a new subcommand into which some environment variables are
exported, eg ssh-agent xterm &. The second is that the agent prints the
needed shell commands (either sh(1) or csh(1) syntax can be generated)
which can be evaluated in the calling shell, eg eval `ssh-agent -s` for
Bourne-type shells such as sh(1) or ksh(1) and eval `ssh-agent -c` for
csh(1) and derivatives.
Later ssh(1) looks at these variables and uses them to establish a
connection to the agent.
The agent will never send a private key over its request channel.
Instead, operations that require a private key will be performed by the
agent, and the result will be returned to the requester. This way,
private keys are not exposed to clients using the agent.
A UNIX-domain socket is created and the name of this socket is stored in
the SSH_AUTH_SOCK environment variable. The socket is made accessible
only to the current user. This method is easily abused by root or
another instance of the same user.
The SSH_AGENT_PID environment variable holds the agent's process ID.
The agent exits automatically when the command given on the command line
terminates.
FILES
$TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>
UNIX-domain sockets used to contain the connection to the
authentication agent. These sockets should only be readable by
the owner. The sockets should get automatically removed when the
agent exits.
SEE ALSO
ssh(1), ssh-add(1), ssh-keygen(1), sshd(8)
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
-OpenBSD 6.4 November 30, 2016 OpenBSD 6.4
+OpenBSD 6.5 November 30, 2016 OpenBSD 6.5
diff --git a/ssh-agent.c b/ssh-agent.c
index d8a8260f9bfd..d06ecfd98a9a 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,1339 +1,1349 @@
-/* $OpenBSD: ssh-agent.c,v 1.231 2018/05/11 03:38:51 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.233 2019/01/22 22:58:50 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* The authentication agent program.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
#include "openbsd-compat/sys-queue.h"
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include "openbsd-compat/openssl-compat.h"
#endif
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#ifdef HAVE_POLL_H
# include <poll.h>
#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_UTIL_H
# include <util.h>
#endif
#include "xmalloc.h"
#include "ssh.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "authfd.h"
#include "compat.h"
#include "log.h"
#include "misc.h"
#include "digest.h"
#include "ssherr.h"
#include "match.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
#endif
#ifndef DEFAULT_PKCS11_WHITELIST
# define DEFAULT_PKCS11_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
#endif
/* Maximum accepted message length */
#define AGENT_MAX_LEN (256*1024)
+/* Maximum bytes to read from client socket */
+#define AGENT_RBUF_LEN (4096)
typedef enum {
AUTH_UNUSED,
AUTH_SOCKET,
AUTH_CONNECTION
} sock_type;
typedef struct {
int fd;
sock_type type;
struct sshbuf *input;
struct sshbuf *output;
struct sshbuf *request;
} SocketEntry;
u_int sockets_alloc = 0;
SocketEntry *sockets = NULL;
typedef struct identity {
TAILQ_ENTRY(identity) next;
struct sshkey *key;
char *comment;
char *provider;
time_t death;
u_int confirm;
} Identity;
struct idtable {
int nentries;
TAILQ_HEAD(idqueue, identity) idlist;
};
/* private key table */
struct idtable *idtab;
int max_fd = 0;
/* pid of shell == parent of agent */
pid_t parent_pid = -1;
time_t parent_alive_interval = 0;
/* pid of process for which cleanup_socket is applicable */
pid_t cleanup_pid = 0;
/* pathname and directory for AUTH_SOCKET */
char socket_name[PATH_MAX];
char socket_dir[PATH_MAX];
/* PKCS#11 path whitelist */
static char *pkcs11_whitelist;
/* locking */
#define LOCK_SIZE 32
#define LOCK_SALT_SIZE 16
#define LOCK_ROUNDS 1
int locked = 0;
u_char lock_pwhash[LOCK_SIZE];
u_char lock_salt[LOCK_SALT_SIZE];
extern char *__progname;
/* Default lifetime in seconds (0 == forever) */
static long lifetime = 0;
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
static void
close_socket(SocketEntry *e)
{
close(e->fd);
e->fd = -1;
e->type = AUTH_UNUSED;
sshbuf_free(e->input);
sshbuf_free(e->output);
sshbuf_free(e->request);
}
static void
idtab_init(void)
{
idtab = xcalloc(1, sizeof(*idtab));
TAILQ_INIT(&idtab->idlist);
idtab->nentries = 0;
}
static void
free_identity(Identity *id)
{
sshkey_free(id->key);
free(id->provider);
free(id->comment);
free(id);
}
/* return matching private key for given public key */
static Identity *
lookup_identity(struct sshkey *key)
{
Identity *id;
TAILQ_FOREACH(id, &idtab->idlist, next) {
if (sshkey_equal(key, id->key))
return (id);
}
return (NULL);
}
/* Check confirmation of keysign request */
static int
confirm_key(Identity *id)
{
char *p;
int ret = -1;
p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
if (p != NULL &&
ask_permission("Allow use of key %s?\nKey fingerprint %s.",
id->comment, p))
ret = 0;
free(p);
return (ret);
}
static void
send_status(SocketEntry *e, int success)
{
int r;
if ((r = sshbuf_put_u32(e->output, 1)) != 0 ||
(r = sshbuf_put_u8(e->output, success ?
SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e)
{
Identity *id;
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
(r = sshbuf_put_u32(msg, idtab->nentries)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
TAILQ_FOREACH(id, &idtab->idlist, next) {
if ((r = sshkey_puts_opts(id->key, msg, SSHKEY_SERIALIZE_INFO))
!= 0 ||
(r = sshbuf_put_cstring(msg, id->comment)) != 0) {
error("%s: put key/comment: %s", __func__,
ssh_err(r));
continue;
}
}
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
}
static char *
agent_decode_alg(struct sshkey *key, u_int flags)
{
if (key->type == KEY_RSA) {
if (flags & SSH_AGENT_RSA_SHA2_256)
return "rsa-sha2-256";
else if (flags & SSH_AGENT_RSA_SHA2_512)
return "rsa-sha2-512";
}
return NULL;
}
/* ssh2 only */
static void
process_sign_request2(SocketEntry *e)
{
const u_char *data;
u_char *signature = NULL;
size_t dlen, slen = 0;
u_int compat = 0, flags;
int r, ok = -1;
struct sshbuf *msg;
struct sshkey *key = NULL;
struct identity *id;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshkey_froms(e->request, &key)) != 0 ||
(r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 ||
(r = sshbuf_get_u32(e->request, &flags)) != 0) {
error("%s: couldn't parse request: %s", __func__, ssh_err(r));
goto send;
}
if ((id = lookup_identity(key)) == NULL) {
verbose("%s: %s key not found", __func__, sshkey_type(key));
goto send;
}
if (id->confirm && confirm_key(id) != 0) {
verbose("%s: user refused key", __func__);
goto send;
}
if ((r = sshkey_sign(id->key, &signature, &slen,
data, dlen, agent_decode_alg(key, flags), compat)) != 0) {
error("%s: sshkey_sign: %s", __func__, ssh_err(r));
goto send;
}
/* Success */
ok = 0;
send:
sshkey_free(key);
if (ok == 0) {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
free(signature);
}
/* shared */
static void
process_remove_identity(SocketEntry *e)
{
int r, success = 0;
struct sshkey *key = NULL;
Identity *id;
if ((r = sshkey_froms(e->request, &key)) != 0) {
error("%s: get key: %s", __func__, ssh_err(r));
goto done;
}
if ((id = lookup_identity(key)) == NULL) {
debug("%s: key not found", __func__);
goto done;
}
/* We have this key, free it. */
if (idtab->nentries < 1)
fatal("%s: internal error: nentries %d",
__func__, idtab->nentries);
TAILQ_REMOVE(&idtab->idlist, id, next);
free_identity(id);
idtab->nentries--;
sshkey_free(key);
success = 1;
done:
send_status(e, success);
}
static void
process_remove_all_identities(SocketEntry *e)
{
Identity *id;
/* Loop over all identities and clear the keys. */
for (id = TAILQ_FIRST(&idtab->idlist); id;
id = TAILQ_FIRST(&idtab->idlist)) {
TAILQ_REMOVE(&idtab->idlist, id, next);
free_identity(id);
}
/* Mark that there are no identities. */
idtab->nentries = 0;
/* Send success. */
send_status(e, 1);
}
/* removes expired keys and returns number of seconds until the next expiry */
static time_t
reaper(void)
{
time_t deadline = 0, now = monotime();
Identity *id, *nxt;
for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
nxt = TAILQ_NEXT(id, next);
if (id->death == 0)
continue;
if (now >= id->death) {
debug("expiring key '%s'", id->comment);
TAILQ_REMOVE(&idtab->idlist, id, next);
free_identity(id);
idtab->nentries--;
} else
deadline = (deadline == 0) ? id->death :
MINIMUM(deadline, id->death);
}
if (deadline == 0 || deadline <= now)
return 0;
else
return (deadline - now);
}
static void
process_add_identity(SocketEntry *e)
{
Identity *id;
int success = 0, confirm = 0;
u_int seconds, maxsign;
char *comment = NULL;
time_t death = 0;
struct sshkey *k = NULL;
u_char ctype;
int r = SSH_ERR_INTERNAL_ERROR;
if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
k == NULL ||
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
error("%s: decode private key: %s", __func__, ssh_err(r));
goto err;
}
while (sshbuf_len(e->request)) {
if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
goto err;
}
switch (ctype) {
case SSH_AGENT_CONSTRAIN_LIFETIME:
if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) {
error("%s: bad lifetime constraint: %s",
__func__, ssh_err(r));
goto err;
}
death = monotime() + seconds;
break;
case SSH_AGENT_CONSTRAIN_CONFIRM:
confirm = 1;
break;
case SSH_AGENT_CONSTRAIN_MAXSIGN:
if ((r = sshbuf_get_u32(e->request, &maxsign)) != 0) {
error("%s: bad maxsign constraint: %s",
__func__, ssh_err(r));
goto err;
}
if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) {
error("%s: cannot enable maxsign: %s",
__func__, ssh_err(r));
goto err;
}
break;
default:
error("%s: Unknown constraint %d", __func__, ctype);
err:
sshbuf_reset(e->request);
free(comment);
sshkey_free(k);
goto send;
}
}
success = 1;
if (lifetime && !death)
death = monotime() + lifetime;
if ((id = lookup_identity(k)) == NULL) {
id = xcalloc(1, sizeof(Identity));
TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
/* Increment the number of identities. */
idtab->nentries++;
} else {
/* key state might have been updated */
sshkey_free(id->key);
free(id->comment);
}
id->key = k;
id->comment = comment;
id->death = death;
id->confirm = confirm;
send:
send_status(e, success);
}
/* XXX todo: encrypt sensitive data with passphrase */
static void
process_lock_agent(SocketEntry *e, int lock)
{
int r, success = 0, delay;
char *passwd;
u_char passwdhash[LOCK_SIZE];
static u_int fail_count = 0;
size_t pwlen;
/*
* This is deliberately fatal: the user has requested that we lock,
* but we can't parse their request properly. The only safe thing to
* do is abort.
*/
if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (pwlen == 0) {
debug("empty password not supported");
} else if (locked && !lock) {
if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0)
fatal("bcrypt_pbkdf");
if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE) == 0) {
debug("agent unlocked");
locked = 0;
fail_count = 0;
explicit_bzero(lock_pwhash, sizeof(lock_pwhash));
success = 1;
} else {
/* delay in 0.1s increments up to 10s */
if (fail_count < 100)
fail_count++;
delay = 100000 * fail_count;
debug("unlock failed, delaying %0.1lf seconds",
(double)delay/1000000);
usleep(delay);
}
explicit_bzero(passwdhash, sizeof(passwdhash));
} else if (!locked && lock) {
debug("agent locked");
locked = 1;
arc4random_buf(lock_salt, sizeof(lock_salt));
if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS) < 0)
fatal("bcrypt_pbkdf");
success = 1;
}
explicit_bzero(passwd, pwlen);
free(passwd);
send_status(e, success);
}
static void
no_identities(SocketEntry *e)
{
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
(r = sshbuf_put_u32(msg, 0)) != 0 ||
(r = sshbuf_put_stringb(e->output, msg)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(msg);
}
#ifdef ENABLE_PKCS11
static void
process_add_smartcard_key(SocketEntry *e)
{
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
int r, i, count = 0, success = 0, confirm = 0;
u_int seconds;
time_t death = 0;
u_char type;
struct sshkey **keys = NULL, *k;
Identity *id;
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
goto send;
}
while (sshbuf_len(e->request)) {
if ((r = sshbuf_get_u8(e->request, &type)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
goto send;
}
switch (type) {
case SSH_AGENT_CONSTRAIN_LIFETIME:
if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) {
error("%s: buffer error: %s",
__func__, ssh_err(r));
goto send;
}
death = monotime() + seconds;
break;
case SSH_AGENT_CONSTRAIN_CONFIRM:
confirm = 1;
break;
default:
error("%s: Unknown constraint type %d", __func__, type);
goto send;
}
}
if (realpath(provider, canonical_provider) == NULL) {
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
provider, strerror(errno));
goto send;
}
if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) {
verbose("refusing PKCS#11 add of \"%.100s\": "
"provider not whitelisted", canonical_provider);
goto send;
}
debug("%s: add %.100s", __func__, canonical_provider);
if (lifetime && !death)
death = monotime() + lifetime;
count = pkcs11_add_provider(canonical_provider, pin, &keys);
for (i = 0; i < count; i++) {
k = keys[i];
if (lookup_identity(k) == NULL) {
id = xcalloc(1, sizeof(Identity));
id->key = k;
id->provider = xstrdup(canonical_provider);
id->comment = xstrdup(canonical_provider); /* XXX */
id->death = death;
id->confirm = confirm;
TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
idtab->nentries++;
success = 1;
} else {
sshkey_free(k);
}
keys[i] = NULL;
}
send:
free(pin);
free(provider);
free(keys);
send_status(e, success);
}
static void
process_remove_smartcard_key(SocketEntry *e)
{
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
int r, success = 0;
Identity *id, *nxt;
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
goto send;
}
free(pin);
if (realpath(provider, canonical_provider) == NULL) {
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
provider, strerror(errno));
goto send;
}
debug("%s: remove %.100s", __func__, canonical_provider);
for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
nxt = TAILQ_NEXT(id, next);
/* Skip file--based keys */
if (id->provider == NULL)
continue;
if (!strcmp(canonical_provider, id->provider)) {
TAILQ_REMOVE(&idtab->idlist, id, next);
free_identity(id);
idtab->nentries--;
}
}
if (pkcs11_del_provider(canonical_provider) == 0)
success = 1;
else
error("%s: pkcs11_del_provider failed", __func__);
send:
free(provider);
send_status(e, success);
}
#endif /* ENABLE_PKCS11 */
/* dispatch incoming messages */
static int
process_message(u_int socknum)
{
u_int msg_len;
u_char type;
const u_char *cp;
int r;
SocketEntry *e;
if (socknum >= sockets_alloc) {
fatal("%s: socket number %u >= allocated %u",
__func__, socknum, sockets_alloc);
}
e = &sockets[socknum];
if (sshbuf_len(e->input) < 5)
return 0; /* Incomplete message header. */
cp = sshbuf_ptr(e->input);
msg_len = PEEK_U32(cp);
if (msg_len > AGENT_MAX_LEN) {
debug("%s: socket %u (fd=%d) message too long %u > %u",
__func__, socknum, e->fd, msg_len, AGENT_MAX_LEN);
return -1;
}
if (sshbuf_len(e->input) < msg_len + 4)
return 0; /* Incomplete message body. */
/* move the current input to e->request */
sshbuf_reset(e->request);
if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 ||
(r = sshbuf_get_u8(e->request, &type)) != 0) {
if (r == SSH_ERR_MESSAGE_INCOMPLETE ||
r == SSH_ERR_STRING_TOO_LARGE) {
debug("%s: buffer error: %s", __func__, ssh_err(r));
return -1;
}
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
debug("%s: socket %u (fd=%d) type %d", __func__, socknum, e->fd, type);
/* check whether agent is locked */
if (locked && type != SSH_AGENTC_UNLOCK) {
sshbuf_reset(e->request);
switch (type) {
case SSH2_AGENTC_REQUEST_IDENTITIES:
/* send empty lists */
no_identities(e);
break;
default:
/* send a fail message for all other request types */
send_status(e, 0);
}
return 0;
}
switch (type) {
case SSH_AGENTC_LOCK:
case SSH_AGENTC_UNLOCK:
process_lock_agent(e, type == SSH_AGENTC_LOCK);
break;
case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
process_remove_all_identities(e); /* safe for !WITH_SSH1 */
break;
/* ssh2 */
case SSH2_AGENTC_SIGN_REQUEST:
process_sign_request2(e);
break;
case SSH2_AGENTC_REQUEST_IDENTITIES:
process_request_identities(e);
break;
case SSH2_AGENTC_ADD_IDENTITY:
case SSH2_AGENTC_ADD_ID_CONSTRAINED:
process_add_identity(e);
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
process_remove_identity(e);
break;
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
process_remove_all_identities(e);
break;
#ifdef ENABLE_PKCS11
case SSH_AGENTC_ADD_SMARTCARD_KEY:
case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED:
process_add_smartcard_key(e);
break;
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
process_remove_smartcard_key(e);
break;
#endif /* ENABLE_PKCS11 */
default:
/* Unknown message. Respond with failure. */
error("Unknown message %d", type);
sshbuf_reset(e->request);
send_status(e, 0);
break;
}
return 0;
}
static void
new_socket(sock_type type, int fd)
{
u_int i, old_alloc, new_alloc;
set_nonblock(fd);
if (fd > max_fd)
max_fd = fd;
for (i = 0; i < sockets_alloc; i++)
if (sockets[i].type == AUTH_UNUSED) {
sockets[i].fd = fd;
if ((sockets[i].input = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((sockets[i].output = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((sockets[i].request = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
sockets[i].type = type;
return;
}
old_alloc = sockets_alloc;
new_alloc = sockets_alloc + 10;
sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0]));
for (i = old_alloc; i < new_alloc; i++)
sockets[i].type = AUTH_UNUSED;
sockets_alloc = new_alloc;
sockets[old_alloc].fd = fd;
if ((sockets[old_alloc].input = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((sockets[old_alloc].output = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((sockets[old_alloc].request = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
sockets[old_alloc].type = type;
}
static int
handle_socket_read(u_int socknum)
{
struct sockaddr_un sunaddr;
socklen_t slen;
uid_t euid;
gid_t egid;
int fd;
slen = sizeof(sunaddr);
fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen);
if (fd < 0) {
error("accept from AUTH_SOCKET: %s", strerror(errno));
return -1;
}
if (getpeereid(fd, &euid, &egid) < 0) {
error("getpeereid %d failed: %s", fd, strerror(errno));
close(fd);
return -1;
}
if ((euid != 0) && (getuid() != euid)) {
error("uid mismatch: peer euid %u != uid %u",
(u_int) euid, (u_int) getuid());
close(fd);
return -1;
}
new_socket(AUTH_CONNECTION, fd);
return 0;
}
static int
handle_conn_read(u_int socknum)
{
- char buf[1024];
+ char buf[AGENT_RBUF_LEN];
ssize_t len;
int r;
if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) {
if (len == -1) {
if (errno == EAGAIN || errno == EINTR)
return 0;
error("%s: read error on socket %u (fd %d): %s",
__func__, socknum, sockets[socknum].fd,
strerror(errno));
}
return -1;
}
if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
explicit_bzero(buf, sizeof(buf));
process_message(socknum);
return 0;
}
static int
handle_conn_write(u_int socknum)
{
ssize_t len;
int r;
if (sshbuf_len(sockets[socknum].output) == 0)
return 0; /* shouldn't happen */
if ((len = write(sockets[socknum].fd,
sshbuf_ptr(sockets[socknum].output),
sshbuf_len(sockets[socknum].output))) <= 0) {
if (len == -1) {
if (errno == EAGAIN || errno == EINTR)
return 0;
error("%s: read error on socket %u (fd %d): %s",
__func__, socknum, sockets[socknum].fd,
strerror(errno));
}
return -1;
}
if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
return 0;
}
static void
after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds)
{
size_t i;
u_int socknum, activefds = npfd;
for (i = 0; i < npfd; i++) {
if (pfd[i].revents == 0)
continue;
/* Find sockets entry */
for (socknum = 0; socknum < sockets_alloc; socknum++) {
if (sockets[socknum].type != AUTH_SOCKET &&
sockets[socknum].type != AUTH_CONNECTION)
continue;
if (pfd[i].fd == sockets[socknum].fd)
break;
}
if (socknum >= sockets_alloc) {
error("%s: no socket for fd %d", __func__, pfd[i].fd);
continue;
}
/* Process events */
switch (sockets[socknum].type) {
case AUTH_SOCKET:
if ((pfd[i].revents & (POLLIN|POLLERR)) == 0)
break;
if (npfd > maxfds) {
debug3("out of fds (active %u >= limit %u); "
"skipping accept", activefds, maxfds);
break;
}
if (handle_socket_read(socknum) == 0)
activefds++;
break;
case AUTH_CONNECTION:
if ((pfd[i].revents & (POLLIN|POLLERR)) != 0 &&
handle_conn_read(socknum) != 0) {
goto close_sock;
}
if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 &&
handle_conn_write(socknum) != 0) {
close_sock:
if (activefds == 0)
fatal("activefds == 0 at close_sock");
close_socket(&sockets[socknum]);
activefds--;
break;
}
break;
default:
break;
}
}
}
static int
prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds)
{
struct pollfd *pfd = *pfdp;
size_t i, j, npfd = 0;
time_t deadline;
+ int r;
/* Count active sockets */
for (i = 0; i < sockets_alloc; i++) {
switch (sockets[i].type) {
case AUTH_SOCKET:
case AUTH_CONNECTION:
npfd++;
break;
case AUTH_UNUSED:
break;
default:
fatal("Unknown socket type %d", sockets[i].type);
break;
}
}
if (npfd != *npfdp &&
(pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL)
fatal("%s: recallocarray failed", __func__);
*pfdp = pfd;
*npfdp = npfd;
for (i = j = 0; i < sockets_alloc; i++) {
switch (sockets[i].type) {
case AUTH_SOCKET:
if (npfd > maxfds) {
debug3("out of fds (active %zu >= limit %u); "
"skipping arming listener", npfd, maxfds);
break;
}
pfd[j].fd = sockets[i].fd;
pfd[j].revents = 0;
pfd[j].events = POLLIN;
j++;
break;
case AUTH_CONNECTION:
pfd[j].fd = sockets[i].fd;
pfd[j].revents = 0;
- /* XXX backoff when input buffer full */
- pfd[j].events = POLLIN;
+ /*
+ * Only prepare to read if we can handle a full-size
+ * input read buffer and enqueue a max size reply..
+ */
+ if ((r = sshbuf_check_reserve(sockets[i].input,
+ AGENT_RBUF_LEN)) == 0 &&
+ (r = sshbuf_check_reserve(sockets[i].output,
+ AGENT_MAX_LEN)) == 0)
+ pfd[j].events = POLLIN;
+ else if (r != SSH_ERR_NO_BUFFER_SPACE) {
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ }
if (sshbuf_len(sockets[i].output) > 0)
pfd[j].events |= POLLOUT;
j++;
break;
default:
break;
}
}
deadline = reaper();
if (parent_alive_interval != 0)
deadline = (deadline == 0) ? parent_alive_interval :
MINIMUM(deadline, parent_alive_interval);
if (deadline == 0) {
*timeoutp = -1; /* INFTIM */
} else {
if (deadline > INT_MAX / 1000)
*timeoutp = INT_MAX / 1000;
else
*timeoutp = deadline * 1000;
}
return (1);
}
static void
cleanup_socket(void)
{
if (cleanup_pid != 0 && getpid() != cleanup_pid)
return;
debug("%s: cleanup", __func__);
if (socket_name[0])
unlink(socket_name);
if (socket_dir[0])
rmdir(socket_dir);
}
void
cleanup_exit(int i)
{
cleanup_socket();
_exit(i);
}
/*ARGSUSED*/
static void
cleanup_handler(int sig)
{
cleanup_socket();
#ifdef ENABLE_PKCS11
pkcs11_terminate();
#endif
_exit(2);
}
static void
check_parent_exists(void)
{
/*
* If our parent has exited then getppid() will return (pid_t)1,
* so testing for that should be safe.
*/
if (parent_pid != -1 && getppid() != parent_pid) {
/* printf("Parent has died - Authentication agent exiting.\n"); */
cleanup_socket();
_exit(2);
}
}
static void
usage(void)
{
fprintf(stderr,
"usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
" [-P pkcs11_whitelist] [-t life] [command [arg ...]]\n"
" ssh-agent [-c | -s] -k\n");
exit(1);
}
int
main(int ac, char **av)
{
int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
int sock, fd, ch, result, saved_errno;
char *shell, *format, *pidstr, *agentsocket = NULL;
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
#endif
extern int optind;
extern char *optarg;
pid_t pid;
char pidstrbuf[1 + 3 * sizeof pid];
size_t len;
mode_t prev_mask;
int timeout = -1; /* INFTIM */
struct pollfd *pfd = NULL;
size_t npfd = 0;
u_int maxfds;
ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
/* drop */
setegid(getgid());
setgid(getgid());
platform_disable_tracing(0); /* strict=no */
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1)
fatal("%s: getrlimit: %s", __progname, strerror(errno));
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
-
__progname = ssh_get_progname(av[0]);
seed_rng();
while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
fatal("Invalid hash algorithm \"%s\"", optarg);
break;
case 'c':
if (s_flag)
usage();
c_flag++;
break;
case 'k':
k_flag++;
break;
case 'P':
if (pkcs11_whitelist != NULL)
fatal("-P option already specified");
pkcs11_whitelist = xstrdup(optarg);
break;
case 's':
if (c_flag)
usage();
s_flag++;
break;
case 'd':
if (d_flag || D_flag)
usage();
d_flag++;
break;
case 'D':
if (d_flag || D_flag)
usage();
D_flag++;
break;
case 'a':
agentsocket = optarg;
break;
case 't':
if ((lifetime = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid lifetime\n");
usage();
}
break;
default:
usage();
}
}
ac -= optind;
av += optind;
if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
usage();
if (pkcs11_whitelist == NULL)
pkcs11_whitelist = xstrdup(DEFAULT_PKCS11_WHITELIST);
if (ac == 0 && !c_flag && !s_flag) {
shell = getenv("SHELL");
if (shell != NULL && (len = strlen(shell)) > 2 &&
strncmp(shell + len - 3, "csh", 3) == 0)
c_flag = 1;
}
if (k_flag) {
const char *errstr = NULL;
pidstr = getenv(SSH_AGENTPID_ENV_NAME);
if (pidstr == NULL) {
fprintf(stderr, "%s not set, cannot kill agent\n",
SSH_AGENTPID_ENV_NAME);
exit(1);
}
pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr);
if (errstr) {
fprintf(stderr,
"%s=\"%s\", which is not a good PID: %s\n",
SSH_AGENTPID_ENV_NAME, pidstr, errstr);
exit(1);
}
if (kill(pid, SIGTERM) == -1) {
perror("kill");
exit(1);
}
format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %ld killed;\n", (long)pid);
exit(0);
}
/*
* Minimum file descriptors:
* stdio (3) + listener (1) + syslog (1 maybe) + connection (1) +
* a few spare for libc / stack protectors / sanitisers, etc.
*/
#define SSH_AGENT_MIN_FDS (3+1+1+1+4)
if (rlim.rlim_cur < SSH_AGENT_MIN_FDS)
- fatal("%s: file descriptior rlimit %lld too low (minimum %u)",
+ fatal("%s: file descriptor rlimit %lld too low (minimum %u)",
__progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS);
maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS;
parent_pid = getpid();
if (agentsocket == NULL) {
/* Create private directory for agent socket */
mktemp_proto(socket_dir, sizeof(socket_dir));
if (mkdtemp(socket_dir) == NULL) {
perror("mkdtemp: private socket dir");
exit(1);
}
snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
(long)parent_pid);
} else {
/* Try to use specified agent socket */
socket_dir[0] = '\0';
strlcpy(socket_name, agentsocket, sizeof socket_name);
}
/*
* Create socket early so it will exist before command gets run from
* the parent.
*/
prev_mask = umask(0177);
sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
if (sock < 0) {
/* XXX - unix_listener() calls error() not perror() */
*socket_name = '\0'; /* Don't unlink any existing file */
cleanup_exit(1);
}
umask(prev_mask);
/*
* Fork, and have the parent execute the command, if any, or present
* the socket data. The child continues as the authentication agent.
*/
if (D_flag || d_flag) {
log_init(__progname,
d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
SYSLOG_FACILITY_AUTH, 1);
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf("echo Agent pid %ld;\n", (long)parent_pid);
fflush(stdout);
goto skip;
}
pid = fork();
if (pid == -1) {
perror("fork");
cleanup_exit(1);
}
if (pid != 0) { /* Parent - execute the given command. */
close(sock);
snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
if (ac == 0) {
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
SSH_AUTHSOCKET_ENV_NAME);
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
SSH_AGENTPID_ENV_NAME);
printf("echo Agent pid %ld;\n", (long)pid);
exit(0);
}
if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
perror("setenv");
exit(1);
}
execvp(av[0], av);
perror(av[0]);
exit(1);
}
/* child */
log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
if (setsid() == -1) {
error("setsid: %s", strerror(errno));
cleanup_exit(1);
}
(void)chdir("/");
if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
/* XXX might close listen socket */
(void)dup2(fd, STDIN_FILENO);
(void)dup2(fd, STDOUT_FILENO);
(void)dup2(fd, STDERR_FILENO);
if (fd > 2)
close(fd);
}
#ifdef HAVE_SETRLIMIT
/* deny core dumps, since memory contains unencrypted private keys */
rlim.rlim_cur = rlim.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
error("setrlimit RLIMIT_CORE: %s", strerror(errno));
cleanup_exit(1);
}
#endif
skip:
cleanup_pid = getpid();
#ifdef ENABLE_PKCS11
pkcs11_init(0);
#endif
new_socket(AUTH_SOCKET, sock);
if (ac > 0)
parent_alive_interval = 10;
idtab_init();
signal(SIGPIPE, SIG_IGN);
signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN);
signal(SIGHUP, cleanup_handler);
signal(SIGTERM, cleanup_handler);
if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1)
fatal("%s: pledge: %s", __progname, strerror(errno));
platform_pledge_agent();
while (1) {
prepare_poll(&pfd, &npfd, &timeout, maxfds);
result = poll(pfd, npfd, timeout);
saved_errno = errno;
if (parent_alive_interval != 0)
check_parent_exists();
(void) reaper(); /* remove expired keys */
if (result < 0) {
if (saved_errno == EINTR)
continue;
fatal("poll: %s", strerror(saved_errno));
} else if (result > 0)
after_poll(pfd, npfd, maxfds);
}
/* NOTREACHED */
}
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 2f553175267e..599c7199db19 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -1,202 +1,200 @@
-/* $OpenBSD: ssh-ecdsa.c,v 1.14 2018/02/07 02:06:51 jsing Exp $ */
+/* $OpenBSD: ssh-ecdsa.c,v 1.16 2019/01/21 09:54:11 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
#include <sys/types.h>
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/evp.h>
#include <string.h>
#include "sshbuf.h"
#include "ssherr.h"
#include "digest.h"
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "openbsd-compat/openssl-compat.h"
/* ARGSUSED */
int
ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat)
{
ECDSA_SIG *sig = NULL;
const BIGNUM *sig_r, *sig_s;
int hash_alg;
u_char digest[SSH_DIGEST_MAX_LENGTH];
size_t len, dlen;
struct sshbuf *b = NULL, *bb = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
if (lenp != NULL)
*lenp = 0;
if (sigp != NULL)
*sigp = NULL;
if (key == NULL || key->ecdsa == NULL ||
sshkey_type_plain(key->type) != KEY_ECDSA)
return SSH_ERR_INVALID_ARGUMENT;
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
(dlen = ssh_digest_bytes(hash_alg)) == 0)
return SSH_ERR_INTERNAL_ERROR;
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
digest, sizeof(digest))) != 0)
goto out;
if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
ECDSA_SIG_get0(sig, &sig_r, &sig_s);
if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 ||
(ret = sshbuf_put_bignum2(bb, sig_s)) != 0)
goto out;
if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
(ret = sshbuf_put_stringb(b, bb)) != 0)
goto out;
len = sshbuf_len(b);
if (sigp != NULL) {
if ((*sigp = malloc(len)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
memcpy(*sigp, sshbuf_ptr(b), len);
}
if (lenp != NULL)
*lenp = len;
ret = 0;
out:
explicit_bzero(digest, sizeof(digest));
sshbuf_free(b);
sshbuf_free(bb);
ECDSA_SIG_free(sig);
return ret;
}
/* ARGSUSED */
int
ssh_ecdsa_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat)
{
ECDSA_SIG *sig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
int hash_alg;
u_char digest[SSH_DIGEST_MAX_LENGTH];
size_t dlen;
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL, *sigbuf = NULL;
char *ktype = NULL;
if (key == NULL || key->ecdsa == NULL ||
sshkey_type_plain(key->type) != KEY_ECDSA ||
signature == NULL || signaturelen == 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
(dlen = ssh_digest_bytes(hash_alg)) == 0)
return SSH_ERR_INTERNAL_ERROR;
/* fetch signature */
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
sshbuf_froms(b, &sigbuf) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
ret = SSH_ERR_KEY_TYPE_MISMATCH;
goto out;
}
if (sshbuf_len(b) != 0) {
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out;
}
/* parse signature */
- if ((sig = ECDSA_SIG_new()) == NULL ||
- (sig_r = BN_new()) == NULL ||
- (sig_s = BN_new()) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
+ if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 ||
+ sshbuf_get_bignum2(sigbuf, &sig_s) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if (sshbuf_get_bignum2(sigbuf, sig_r) != 0 ||
- sshbuf_get_bignum2(sigbuf, sig_s) != 0) {
- ret = SSH_ERR_INVALID_FORMAT;
+ if ((sig = ECDSA_SIG_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
sig_r = sig_s = NULL; /* transferred */
if (sshbuf_len(sigbuf) != 0) {
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out;
}
if ((ret = ssh_digest_memory(hash_alg, data, datalen,
digest, sizeof(digest))) != 0)
goto out;
switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
case 1:
ret = 0;
break;
case 0:
ret = SSH_ERR_SIGNATURE_INVALID;
goto out;
default:
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
out:
explicit_bzero(digest, sizeof(digest));
sshbuf_free(sigbuf);
sshbuf_free(b);
ECDSA_SIG_free(sig);
BN_clear_free(sig_r);
BN_clear_free(sig_s);
free(ktype);
return ret;
}
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
diff --git a/ssh-keygen.0 b/ssh-keygen.0
index 906a338c4eb4..1fe19f0b66cf 100644
--- a/ssh-keygen.0
+++ b/ssh-keygen.0
@@ -1,585 +1,599 @@
SSH-KEYGEN(1) General Commands Manual SSH-KEYGEN(1)
NAME
ssh-keygen M-bM-^@M-^S authentication key generation, management and conversion
SYNOPSIS
ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa]
[-N new_passphrase] [-C comment] [-f output_keyfile]
+ [-m format]
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
+ [-m format]
ssh-keygen -i [-m key_format] [-f input_keyfile]
ssh-keygen -e [-m key_format] [-f input_keyfile]
ssh-keygen -y [-f input_keyfile]
ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]
ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]
ssh-keygen -B [-f input_keyfile]
ssh-keygen -D pkcs11
ssh-keygen -F hostname [-f known_hosts_file] [-l]
ssh-keygen -H [-f known_hosts_file]
ssh-keygen -R hostname [-f known_hosts_file]
ssh-keygen -r hostname [-f input_keyfile] [-g]
ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]
ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]
[-j start_line] [-K checkpt] [-W generator]
ssh-keygen -s ca_key -I certificate_identity [-h] [-U]
[-D pkcs11_provider] [-n principals] [-O option]
[-V validity_interval] [-z serial_number] file ...
ssh-keygen -L [-f input_keyfile]
ssh-keygen -A [-f prefix_path]
ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]
file ...
ssh-keygen -Q -f krl_file file ...
DESCRIPTION
ssh-keygen generates, manages and converts authentication keys for
ssh(1). ssh-keygen can create keys for use by SSH protocol version 2.
The type of key to be generated is specified with the -t option. If
invoked without any arguments, ssh-keygen will generate an RSA key.
ssh-keygen is also used to generate groups for use in Diffie-Hellman
group exchange (DH-GEX). See the MODULI GENERATION section for details.
Finally, ssh-keygen can be used to generate and update Key Revocation
Lists, and to test whether given keys have been revoked by one. See the
KEY REVOCATION LISTS section for details.
Normally each user wishing to use SSH with public key authentication runs
this once to create the authentication key in ~/.ssh/id_dsa,
~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 or ~/.ssh/id_rsa. Additionally, the
system administrator may use this to generate host keys, as seen in
/etc/rc.
Normally this program generates the key and asks for a file in which to
store the private key. The public key is stored in a file with the same
name but M-bM-^@M-^\.pubM-bM-^@M-^] appended. The program also asks for a passphrase. The
passphrase may be empty to indicate no passphrase (host keys must have an
empty passphrase), or it may be a string of arbitrary length. A
passphrase is similar to a password, except it can be a phrase with a
series of words, punctuation, numbers, whitespace, or any string of
characters you want. Good passphrases are 10-30 characters long, are not
simple sentences or otherwise easily guessable (English prose has only
1-2 bits of entropy per character, and provides very bad passphrases),
and contain a mix of upper and lowercase letters, numbers, and non-
alphanumeric characters. The passphrase can be changed later by using
the -p option.
There is no way to recover a lost passphrase. If the passphrase is lost
or forgotten, a new key must be generated and the corresponding public
key copied to other machines.
- For keys stored in the newer OpenSSH format, there is also a comment
- field in the key file that is only for convenience to the user to help
- identify the key. The comment can tell what the key is for, or whatever
- is useful. The comment is initialized to M-bM-^@M-^\user@hostM-bM-^@M-^] when the key is
- created, but can be changed using the -c option.
+ ssh-keygen will by default write keys in an OpenSSH-specific format.
+ This format is preferred as it offers better protection for keys at rest
+ as well as allowing storage of key comments within the private key file
+ itself. The key comment may be useful to help identify the key. The
+ comment is initialized to M-bM-^@M-^\user@hostM-bM-^@M-^] when the key is created, but can be
+ changed using the -c option.
+
+ It is still possible for ssh-keygen to write the previously-used PEM
+ format private keys using the -m flag. This may be used when generating
+ new keys, and existing new-format keys may be converted using this option
+ in conjunction with the -p (change passphrase) flag.
After a key is generated, instructions below detail where the keys should
be placed to be activated.
The options are as follows:
-A For each of the key types (rsa, dsa, ecdsa and ed25519) for which
host keys do not exist, generate the host keys with the default
key file path, an empty passphrase, default bits for the key
type, and default comment. If -f has also been specified, its
argument is used as a prefix to the default path for the
resulting host key files. This is used by /etc/rc to generate
new host keys.
-a rounds
When saving a private key this option specifies the number of KDF
(key derivation function) rounds used. Higher numbers result in
slower passphrase verification and increased resistance to brute-
force password cracking (should the keys be stolen).
When screening DH-GEX candidates (using the -T command). This
option specifies the number of primality tests to perform.
-B Show the bubblebabble digest of specified private or public key
file.
-b bits
Specifies the number of bits in the key to create. For RSA keys,
the minimum size is 1024 bits and the default is 2048 bits.
Generally, 2048 bits is considered sufficient. DSA keys must be
exactly 1024 bits as specified by FIPS 186-2. For ECDSA keys,
the -b flag determines the key length by selecting from one of
three elliptic curve sizes: 256, 384 or 521 bits. Attempting to
use bit lengths other than these three values for ECDSA keys will
fail. Ed25519 keys have a fixed length and the -b flag will be
ignored.
-C comment
Provides a new comment.
-c Requests changing the comment in the private and public key
files. The program will prompt for the file containing the
private keys, for the passphrase if the key has one, and for the
new comment.
-D pkcs11
- Download the RSA public keys provided by the PKCS#11 shared
- library pkcs11. When used in combination with -s, this option
- indicates that a CA key resides in a PKCS#11 token (see the
- CERTIFICATES section for details).
+ Download the public keys provided by the PKCS#11 shared library
+ pkcs11. When used in combination with -s, this option indicates
+ that a CA key resides in a PKCS#11 token (see the CERTIFICATES
+ section for details).
-E fingerprint_hash
Specifies the hash algorithm used when displaying key
fingerprints. Valid options are: M-bM-^@M-^\md5M-bM-^@M-^] and M-bM-^@M-^\sha256M-bM-^@M-^]. The
default is M-bM-^@M-^\sha256M-bM-^@M-^].
-e This option will read a private or public OpenSSH key file and
- print to stdout the key in one of the formats specified by the -m
- option. The default export format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. This option
- allows exporting OpenSSH keys for use by other programs,
+ print to stdout a public key in one of the formats specified by
+ the -m option. The default export format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. This
+ option allows exporting OpenSSH keys for use by other programs,
including several commercial SSH implementations.
- -F hostname
- Search for the specified hostname in a known_hosts file, listing
- any occurrences found. This option is useful to find hashed host
- names or addresses and may also be used in conjunction with the
- -H option to print found keys in a hashed format.
+ -F hostname | [hostname]:port
+ Search for the specified hostname (with optional port number) in
+ a known_hosts file, listing any occurrences found. This option
+ is useful to find hashed host names or addresses and may also be
+ used in conjunction with the -H option to print found keys in a
+ hashed format.
-f filename
Specifies the filename of the key file.
-G output_file
Generate candidate primes for DH-GEX. These primes must be
screened for safety (using the -T option) before use.
-g Use generic DNS format when printing fingerprint resource records
using the -r command.
-H Hash a known_hosts file. This replaces all hostnames and
addresses with hashed representations within the specified file;
the original content is moved to a file with a .old suffix.
These hashes may be used normally by ssh and sshd, but they do
not reveal identifying information should the file's contents be
disclosed. This option will not modify existing hashed hostnames
and is therefore safe to use on files that mix hashed and non-
hashed names.
-h When signing a key, create a host certificate instead of a user
certificate. Please see the CERTIFICATES section for details.
-I certificate_identity
Specify the key identity when signing a public key. Please see
the CERTIFICATES section for details.
-i This option will read an unencrypted private (or public) key file
in the format specified by the -m option and print an OpenSSH
compatible private (or public) key to stdout. This option allows
importing keys from other software, including several commercial
SSH implementations. The default import format is M-bM-^@M-^\RFC4716M-bM-^@M-^].
-J num_lines
Exit after screening the specified number of lines while
performing DH candidate screening using the -T option.
-j start_line
Start screening at the specified line number while performing DH
candidate screening using the -T option.
-K checkpt
Write the last line processed to the file checkpt while
performing DH candidate screening using the -T option. This will
be used to skip lines in the input file that have already been
processed if the job is restarted.
-k Generate a KRL file. In this mode, ssh-keygen will generate a
KRL file at the location specified via the -f flag that revokes
every key or certificate presented on the command line.
Keys/certificates to be revoked may be specified by public key
file or using the format described in the KEY REVOCATION LISTS
section.
-L Prints the contents of one or more certificates.
-l Show fingerprint of specified public key file. For RSA and DSA
keys ssh-keygen tries to find the matching public key file and
prints its fingerprint. If combined with -v, a visual ASCII art
representation of the key is supplied with the fingerprint.
-M memory
Specify the amount of memory to use (in megabytes) when
generating candidate moduli for DH-GEX.
-m key_format
- Specify a key format for the -i (import) or -e (export)
- conversion options. The supported key formats are: M-bM-^@M-^\RFC4716M-bM-^@M-^]
- (RFC 4716/SSH2 public or private key), M-bM-^@M-^\PKCS8M-bM-^@M-^] (PEM PKCS8 public
- key) or M-bM-^@M-^\PEMM-bM-^@M-^] (PEM public key). The default conversion format is
- M-bM-^@M-^\RFC4716M-bM-^@M-^]. Setting a format of M-bM-^@M-^\PEMM-bM-^@M-^] when generating or updating
- a supported private key type will cause the key to be stored in
- the legacy PEM private key format.
+ Specify a key format for key generation, the -i (import), -e
+ (export) conversion options, and the -p change passphrase
+ operation. The latter may be used to convert between OpenSSH
+ private key and PEM private key formats. The supported key
+ formats are: M-bM-^@M-^\RFC4716M-bM-^@M-^] (RFC 4716/SSH2 public or private key),
+ M-bM-^@M-^\PKCS8M-bM-^@M-^] (PEM PKCS8 public key) or M-bM-^@M-^\PEMM-bM-^@M-^] (PEM public key). The
+ default conversion format is M-bM-^@M-^\RFC4716M-bM-^@M-^]. Setting a format of
+ M-bM-^@M-^\PEMM-bM-^@M-^] when generating or updating a supported private key type
+ will cause the key to be stored in the legacy PEM private key
+ format.
-N new_passphrase
Provides the new passphrase.
-n principals
Specify one or more principals (user or host names) to be
included in a certificate when signing a key. Multiple
principals may be specified, separated by commas. Please see the
CERTIFICATES section for details.
-O option
Specify a certificate option when signing a key. This option may
be specified multiple times. See also the CERTIFICATES section
for further details.
At present, no standard options are valid for host keys. The
options that are valid for user certificates are:
clear Clear all enabled permissions. This is useful for
clearing the default set of permissions so permissions
may be added individually.
critical:name[=contents]
extension:name[=contents]
Includes an arbitrary certificate critical option or
extension. The specified name should include a domain
suffix, e.g. M-bM-^@M-^\name@example.comM-bM-^@M-^]. If contents is
specified then it is included as the contents of the
extension/option encoded as a string, otherwise the
extension/option is created with no contents (usually
indicating a flag). Extensions may be ignored by a
client or server that does not recognise them, whereas
unknown critical options will cause the certificate to be
refused.
force-command=command
Forces the execution of command instead of any shell or
command specified by the user when the certificate is
used for authentication.
no-agent-forwarding
Disable ssh-agent(1) forwarding (permitted by default).
no-port-forwarding
Disable port forwarding (permitted by default).
no-pty Disable PTY allocation (permitted by default).
no-user-rc
Disable execution of ~/.ssh/rc by sshd(8) (permitted by
default).
no-x11-forwarding
Disable X11 forwarding (permitted by default).
permit-agent-forwarding
Allows ssh-agent(1) forwarding.
permit-port-forwarding
Allows port forwarding.
permit-pty
Allows PTY allocation.
permit-user-rc
Allows execution of ~/.ssh/rc by sshd(8).
permit-X11-forwarding
Allows X11 forwarding.
source-address=address_list
Restrict the source addresses from which the certificate
is considered valid. The address_list is a comma-
separated list of one or more address/netmask pairs in
CIDR format.
-P passphrase
Provides the (old) passphrase.
-p Requests changing the passphrase of a private key file instead of
creating a new private key. The program will prompt for the file
containing the private key, for the old passphrase, and twice for
the new passphrase.
-Q Test whether keys have been revoked in a KRL.
-q Silence ssh-keygen.
- -R hostname
- Removes all keys belonging to hostname from a known_hosts file.
- This option is useful to delete hashed hosts (see the -H option
- above).
+ -R hostname | [hostname]:port
+ Removes all keys belonging to the specified hostname (with
+ optional port number) from a known_hosts file. This option is
+ useful to delete hashed hosts (see the -H option above).
-r hostname
Print the SSHFP fingerprint resource record named hostname for
the specified public key file.
-S start
Specify start point (in hex) when generating candidate moduli for
DH-GEX.
-s ca_key
Certify (sign) a public key using the specified CA key. Please
see the CERTIFICATES section for details.
When generating a KRL, -s specifies a path to a CA public key
file used to revoke certificates directly by key ID or serial
number. See the KEY REVOCATION LISTS section for details.
-T output_file
Test DH group exchange candidate primes (generated using the -G
option) for safety.
-t dsa | ecdsa | ed25519 | rsa
Specifies the type of key to create. The possible values are
M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^].
-U When used in combination with -s, this option indicates that a CA
key resides in a ssh-agent(1). See the CERTIFICATES section for
more information.
-u Update a KRL. When specified with -k, keys listed via the
command line are added to the existing KRL rather than a new KRL
being created.
-V validity_interval
Specify a validity interval when signing a certificate. A
validity interval may consist of a single time, indicating that
the certificate is valid beginning now and expiring at that time,
or may consist of two times separated by a colon to indicate an
explicit time interval.
The start time may be specified as the string M-bM-^@M-^\alwaysM-bM-^@M-^] to
indicate the certificate has no specified start time, a date in
YYYYMMDD format, a time in YYYYMMDDHHMM[SS] format, a relative
time (to the current time) consisting of a minus sign followed by
an interval in the format described in the TIME FORMATS section
of sshd_config(5).
The end time may be specified as a YYYYMMDD date, a
YYYYMMDDHHMM[SS] time, a relative time starting with a plus
character or the string M-bM-^@M-^\foreverM-bM-^@M-^] to indicate that the
certificate has no expirty date.
For example: M-bM-^@M-^\+52w1dM-bM-^@M-^] (valid from now to 52 weeks and one day
from now), M-bM-^@M-^\-4w:+4wM-bM-^@M-^] (valid from four weeks ago to four weeks
from now), M-bM-^@M-^\20100101123000:20110101123000M-bM-^@M-^] (valid from 12:30 PM,
January 1st, 2010 to 12:30 PM, January 1st, 2011), M-bM-^@M-^\-1d:20110101M-bM-^@M-^]
(valid from yesterday to midnight, January 1st, 2011).
M-bM-^@M-^\-1m:foreverM-bM-^@M-^] (valid from one minute ago and never expiring).
-v Verbose mode. Causes ssh-keygen to print debugging messages
about its progress. This is helpful for debugging moduli
generation. Multiple -v options increase the verbosity. The
maximum is 3.
-W generator
Specify desired generator when testing candidate moduli for DH-
GEX.
-y This option will read a private OpenSSH format file and print an
OpenSSH public key to stdout.
-z serial_number
Specifies a serial number to be embedded in the certificate to
- distinguish this certificate from others from the same CA. The
- default serial number is zero.
+ distinguish this certificate from others from the same CA. If
+ the serial_number is prefixed with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the
+ serial number will be incremented for each certificate signed on
+ a single command-line. The default serial number is zero.
When generating a KRL, the -z flag is used to specify a KRL
version number.
MODULI GENERATION
ssh-keygen may be used to generate groups for the Diffie-Hellman Group
Exchange (DH-GEX) protocol. Generating these groups is a two-step
process: first, candidate primes are generated using a fast, but memory
intensive process. These candidate primes are then tested for
suitability (a CPU-intensive process).
Generation of primes is performed using the -G option. The desired
length of the primes may be specified by the -b option. For example:
# ssh-keygen -G moduli-2048.candidates -b 2048
By default, the search for primes begins at a random point in the desired
length range. This may be overridden using the -S option, which
specifies a different start point (in hex).
Once a set of candidates have been generated, they must be screened for
suitability. This may be performed using the -T option. In this mode
ssh-keygen will read candidates from standard input (or a file specified
using the -f option). For example:
# ssh-keygen -T moduli-2048 -f moduli-2048.candidates
By default, each candidate will be subjected to 100 primality tests.
This may be overridden using the -a option. The DH generator value will
be chosen automatically for the prime under consideration. If a specific
generator is desired, it may be requested using the -W option. Valid
generator values are 2, 3, and 5.
Screened DH groups may be installed in /etc/moduli. It is important that
this file contains moduli of a range of bit lengths and that both ends of
a connection share common moduli.
CERTIFICATES
ssh-keygen supports signing of keys to produce certificates that may be
used for user or host authentication. Certificates consist of a public
key, some identity information, zero or more principal (user or host)
names and a set of options that are signed by a Certification Authority
(CA) key. Clients or servers may then trust only the CA key and verify
its signature on a certificate rather than trusting many user/host keys.
Note that OpenSSH certificates are a different, and much simpler, format
to the X.509 certificates used in ssl(8).
ssh-keygen supports two types of certificates: user and host. User
certificates authenticate users to servers, whereas host certificates
authenticate server hosts to users. To generate a user certificate:
$ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
The resultant certificate will be placed in /path/to/user_key-cert.pub.
A host certificate requires the -h option:
$ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
The host certificate will be output to /path/to/host_key-cert.pub.
It is possible to sign using a CA key stored in a PKCS#11 token by
providing the token library using -D and identifying the CA key by
providing its public half as an argument to -s:
$ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub
Similarly, it is possible for the CA key to be hosted in a ssh-agent(1).
This is indicated by the -U flag and, again, the CA key must be
identified by its public half.
$ ssh-keygen -Us ca_key.pub -I key_id user_key.pub
In all cases, key_id is a "key identifier" that is logged by the server
when the certificate is used for authentication.
Certificates may be limited to be valid for a set of principal
(user/host) names. By default, generated certificates are valid for all
users or hosts. To generate a certificate for a specified set of
principals:
$ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
$ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub
Additional limitations on the validity and use of user certificates may
be specified through certificate options. A certificate option may
disable features of the SSH session, may be valid only when presented
from particular source addresses or may force the use of a specific
command. For a list of valid certificate options, see the documentation
for the -O option above.
Finally, certificates may be defined with a validity lifetime. The -V
option allows specification of certificate start and end times. A
certificate that is presented at a time outside this range will not be
considered valid. By default, certificates are valid from UNIX Epoch to
the distant future.
For certificates to be used for user or host authentication, the CA
public key must be trusted by sshd(8) or ssh(1). Please refer to those
manual pages for details.
KEY REVOCATION LISTS
ssh-keygen is able to manage OpenSSH format Key Revocation Lists (KRLs).
These binary files specify keys or certificates to be revoked using a
compact format, taking as little as one bit per certificate if they are
being revoked by serial number.
KRLs may be generated using the -k flag. This option reads one or more
files from the command line and generates a new KRL. The files may
either contain a KRL specification (see below) or public keys, listed one
per line. Plain public keys are revoked by listing their hash or
contents in the KRL and certificates revoked by serial number or key ID
(if the serial is zero or not available).
Revoking keys using a KRL specification offers explicit control over the
types of record used to revoke keys and may be used to directly revoke
certificates by serial number or key ID without having the complete
original certificate on hand. A KRL specification consists of lines
containing one of the following directives followed by a colon and some
directive-specific information.
serial: serial_number[-serial_number]
Revokes a certificate with the specified serial number. Serial
numbers are 64-bit values, not including zero and may be
expressed in decimal, hex or octal. If two serial numbers are
specified separated by a hyphen, then the range of serial numbers
including and between each is revoked. The CA key must have been
specified on the ssh-keygen command line using the -s option.
id: key_id
Revokes a certificate with the specified key ID string. The CA
key must have been specified on the ssh-keygen command line using
the -s option.
key: public_key
Revokes the specified key. If a certificate is listed, then it
is revoked as a plain public key.
sha1: public_key
Revokes the specified key by including its SHA1 hash in the KRL.
sha256: public_key
Revokes the specified key by including its SHA256 hash in the
KRL. KRLs that revoke keys by SHA256 hash are not supported by
OpenSSH versions prior to 7.9.
hash: fingerprint
Revokes a key using a fingerprint hash, as obtained from a
sshd(8) authentication log message or the ssh-keygen -l flag.
Only SHA256 fingerprints are supported here and resultant KRLs
are not supported by OpenSSH versions prior to 7.9.
KRLs may be updated using the -u flag in addition to -k. When this
option is specified, keys listed via the command line are merged into the
KRL, adding to those already there.
It is also possible, given a KRL, to test whether it revokes a particular
key (or keys). The -Q flag will query an existing KRL, testing each key
specified on the command line. If any key listed on the command line has
been revoked (or an error encountered) then ssh-keygen will exit with a
non-zero exit status. A zero exit status will only be returned if no key
was revoked.
FILES
~/.ssh/id_dsa
~/.ssh/id_ecdsa
~/.ssh/id_ed25519
~/.ssh/id_rsa
Contains the DSA, ECDSA, Ed25519 or RSA authentication identity
of the user. This file should not be readable by anyone but the
user. It is possible to specify a passphrase when generating the
key; that passphrase will be used to encrypt the private part of
this file using 128-bit AES. This file is not automatically
accessed by ssh-keygen but it is offered as the default file for
the private key. ssh(1) will read this file when a login attempt
is made.
~/.ssh/id_dsa.pub
~/.ssh/id_ecdsa.pub
~/.ssh/id_ed25519.pub
~/.ssh/id_rsa.pub
Contains the DSA, ECDSA, Ed25519 or RSA public key for
authentication. The contents of this file should be added to
~/.ssh/authorized_keys on all machines where the user wishes to
log in using public key authentication. There is no need to keep
the contents of this file secret.
/etc/moduli
Contains Diffie-Hellman groups used for DH-GEX. The file format
is described in moduli(5).
SEE ALSO
ssh(1), ssh-add(1), ssh-agent(1), moduli(5), sshd(8)
The Secure Shell (SSH) Public Key File Format, RFC 4716, 2006.
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
-OpenBSD 6.4 September 12, 2018 OpenBSD 6.4
+OpenBSD 6.5 March 5, 2019 OpenBSD 6.5
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index bfa2eb5f3e37..124456577c4e 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,904 +1,930 @@
-.\" $OpenBSD: ssh-keygen.1,v 1.150 2018/09/12 06:18:59 djm Exp $
+.\" $OpenBSD: ssh-keygen.1,v 1.157 2019/03/05 16:17:12 naddy Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" As far as I am concerned, the code I have written for this software
.\" can be used freely for any purpose. Any derived versions of this
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: September 12 2018 $
+.Dd $Mdocdate: March 5 2019 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
.Nm ssh-keygen
.Nd authentication key generation, management and conversion
.Sh SYNOPSIS
.Bk -words
.Nm ssh-keygen
.Op Fl q
.Op Fl b Ar bits
.Op Fl t Cm dsa | ecdsa | ed25519 | rsa
.Op Fl N Ar new_passphrase
.Op Fl C Ar comment
.Op Fl f Ar output_keyfile
+.Op Fl m Ar format
.Nm ssh-keygen
.Fl p
.Op Fl P Ar old_passphrase
.Op Fl N Ar new_passphrase
.Op Fl f Ar keyfile
+.Op Fl m Ar format
.Nm ssh-keygen
.Fl i
.Op Fl m Ar key_format
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl e
.Op Fl m Ar key_format
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl y
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl c
.Op Fl P Ar passphrase
.Op Fl C Ar comment
.Op Fl f Ar keyfile
.Nm ssh-keygen
.Fl l
.Op Fl v
.Op Fl E Ar fingerprint_hash
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl B
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl D Ar pkcs11
.Nm ssh-keygen
.Fl F Ar hostname
.Op Fl f Ar known_hosts_file
.Op Fl l
.Nm ssh-keygen
.Fl H
.Op Fl f Ar known_hosts_file
.Nm ssh-keygen
.Fl R Ar hostname
.Op Fl f Ar known_hosts_file
.Nm ssh-keygen
.Fl r Ar hostname
.Op Fl f Ar input_keyfile
.Op Fl g
.Nm ssh-keygen
.Fl G Ar output_file
.Op Fl v
.Op Fl b Ar bits
.Op Fl M Ar memory
.Op Fl S Ar start_point
.Nm ssh-keygen
.Fl T Ar output_file
.Fl f Ar input_file
.Op Fl v
.Op Fl a Ar rounds
.Op Fl J Ar num_lines
.Op Fl j Ar start_line
.Op Fl K Ar checkpt
.Op Fl W Ar generator
.Nm ssh-keygen
.Fl s Ar ca_key
.Fl I Ar certificate_identity
.Op Fl h
.Op Fl U
.Op Fl D Ar pkcs11_provider
.Op Fl n Ar principals
.Op Fl O Ar option
.Op Fl V Ar validity_interval
.Op Fl z Ar serial_number
.Ar
.Nm ssh-keygen
.Fl L
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl A
.Op Fl f Ar prefix_path
.Nm ssh-keygen
.Fl k
.Fl f Ar krl_file
.Op Fl u
.Op Fl s Ar ca_public
.Op Fl z Ar version_number
.Ar
.Nm ssh-keygen
.Fl Q
.Fl f Ar krl_file
.Ar
.Ek
.Sh DESCRIPTION
.Nm
generates, manages and converts authentication keys for
.Xr ssh 1 .
.Nm
can create keys for use by SSH protocol version 2.
.Pp
The type of key to be generated is specified with the
.Fl t
option.
If invoked without any arguments,
.Nm
will generate an RSA key.
.Pp
.Nm
is also used to generate groups for use in Diffie-Hellman group
exchange (DH-GEX).
See the
.Sx MODULI GENERATION
section for details.
.Pp
Finally,
.Nm
can be used to generate and update Key Revocation Lists, and to test whether
given keys have been revoked by one.
See the
.Sx KEY REVOCATION LISTS
section for details.
.Pp
Normally each user wishing to use SSH
with public key authentication runs this once to create the authentication
key in
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
.Pa ~/.ssh/id_ed25519
or
.Pa ~/.ssh/id_rsa .
Additionally, the system administrator may use this to generate host keys,
as seen in
.Pa /etc/rc .
.Pp
Normally this program generates the key and asks for a file in which
to store the private key.
The public key is stored in a file with the same name but
.Dq .pub
appended.
The program also asks for a passphrase.
The passphrase may be empty to indicate no passphrase
(host keys must have an empty passphrase), or it may be a string of
arbitrary length.
A passphrase is similar to a password, except it can be a phrase with a
series of words, punctuation, numbers, whitespace, or any string of
characters you want.
Good passphrases are 10-30 characters long, are
not simple sentences or otherwise easily guessable (English
prose has only 1-2 bits of entropy per character, and provides very bad
passphrases), and contain a mix of upper and lowercase letters,
numbers, and non-alphanumeric characters.
The passphrase can be changed later by using the
.Fl p
option.
.Pp
There is no way to recover a lost passphrase.
If the passphrase is lost or forgotten, a new key must be generated
and the corresponding public key copied to other machines.
.Pp
-For keys stored in the newer OpenSSH format,
-there is also a comment field in the key file that is only for
-convenience to the user to help identify the key.
-The comment can tell what the key is for, or whatever is useful.
+.Nm
+will by default write keys in an OpenSSH-specific format.
+This format is preferred as it offers better protection for
+keys at rest as well as allowing storage of key comments within
+the private key file itself.
+The key comment may be useful to help identify the key.
The comment is initialized to
.Dq user@host
when the key is created, but can be changed using the
.Fl c
option.
.Pp
+It is still possible for
+.Nm
+to write the previously-used PEM format private keys using the
+.Fl m
+flag.
+This may be used when generating new keys, and existing new-format
+keys may be converted using this option in conjunction with the
+.Fl p
+(change passphrase) flag.
+.Pp
After a key is generated, instructions below detail where the keys
should be placed to be activated.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl A
For each of the key types (rsa, dsa, ecdsa and ed25519)
for which host keys
do not exist, generate the host keys with the default key file path,
an empty passphrase, default bits for the key type, and default comment.
If
.Fl f
has also been specified, its argument is used as a prefix to the
default path for the resulting host key files.
This is used by
.Pa /etc/rc
to generate new host keys.
.It Fl a Ar rounds
When saving a private key this option specifies the number of KDF
(key derivation function) rounds used.
Higher numbers result in slower passphrase verification and increased
resistance to brute-force password cracking (should the keys be stolen).
.Pp
When screening DH-GEX candidates (using the
.Fl T
command).
This option specifies the number of primality tests to perform.
.It Fl B
Show the bubblebabble digest of specified private or public key file.
.It Fl b Ar bits
Specifies the number of bits in the key to create.
For RSA keys, the minimum size is 1024 bits and the default is 2048 bits.
Generally, 2048 bits is considered sufficient.
DSA keys must be exactly 1024 bits as specified by FIPS 186-2.
For ECDSA keys, the
.Fl b
flag determines the key length by selecting from one of three elliptic
curve sizes: 256, 384 or 521 bits.
Attempting to use bit lengths other than these three values for ECDSA keys
will fail.
Ed25519 keys have a fixed length and the
.Fl b
flag will be ignored.
.It Fl C Ar comment
Provides a new comment.
.It Fl c
Requests changing the comment in the private and public key files.
The program will prompt for the file containing the private keys, for
the passphrase if the key has one, and for the new comment.
.It Fl D Ar pkcs11
-Download the RSA public keys provided by the PKCS#11 shared library
+Download the public keys provided by the PKCS#11 shared library
.Ar pkcs11 .
When used in combination with
.Fl s ,
this option indicates that a CA key resides in a PKCS#11 token (see the
.Sx CERTIFICATES
section for details).
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
.Dq sha256 .
.It Fl e
This option will read a private or public OpenSSH key file and
-print to stdout the key in one of the formats specified by the
+print to stdout a public key in one of the formats specified by the
.Fl m
option.
The default export format is
.Dq RFC4716 .
This option allows exporting OpenSSH keys for use by other programs, including
several commercial SSH implementations.
-.It Fl F Ar hostname
+.It Fl F Ar hostname | [hostname]:port
Search for the specified
.Ar hostname
+(with optional port number)
in a
.Pa known_hosts
file, listing any occurrences found.
This option is useful to find hashed host names or addresses and may also be
used in conjunction with the
.Fl H
option to print found keys in a hashed format.
.It Fl f Ar filename
Specifies the filename of the key file.
.It Fl G Ar output_file
Generate candidate primes for DH-GEX.
These primes must be screened for
safety (using the
.Fl T
option) before use.
.It Fl g
Use generic DNS format when printing fingerprint resource records using the
.Fl r
command.
.It Fl H
Hash a
.Pa known_hosts
file.
This replaces all hostnames and addresses with hashed representations
within the specified file; the original content is moved to a file with
a .old suffix.
These hashes may be used normally by
.Nm ssh
and
.Nm sshd ,
but they do not reveal identifying information should the file's contents
be disclosed.
This option will not modify existing hashed hostnames and is therefore safe
to use on files that mix hashed and non-hashed names.
.It Fl h
When signing a key, create a host certificate instead of a user
certificate.
Please see the
.Sx CERTIFICATES
section for details.
.It Fl I Ar certificate_identity
Specify the key identity when signing a public key.
Please see the
.Sx CERTIFICATES
section for details.
.It Fl i
This option will read an unencrypted private (or public) key file
in the format specified by the
.Fl m
option and print an OpenSSH compatible private
(or public) key to stdout.
This option allows importing keys from other software, including several
commercial SSH implementations.
The default import format is
.Dq RFC4716 .
.It Fl J Ar num_lines
Exit after screening the specified number of lines
while performing DH candidate screening using the
.Fl T
option.
.It Fl j Ar start_line
Start screening at the specified line number
while performing DH candidate screening using the
.Fl T
option.
.It Fl K Ar checkpt
Write the last line processed to the file
.Ar checkpt
while performing DH candidate screening using the
.Fl T
option.
This will be used to skip lines in the input file that have already been
processed if the job is restarted.
.It Fl k
Generate a KRL file.
In this mode,
.Nm
will generate a KRL file at the location specified via the
.Fl f
flag that revokes every key or certificate presented on the command line.
Keys/certificates to be revoked may be specified by public key file or
using the format described in the
.Sx KEY REVOCATION LISTS
section.
.It Fl L
Prints the contents of one or more certificates.
.It Fl l
Show fingerprint of specified public key file.
For RSA and DSA keys
.Nm
tries to find the matching public key file and prints its fingerprint.
If combined with
.Fl v ,
a visual ASCII art representation of the key is supplied with the
fingerprint.
.It Fl M Ar memory
Specify the amount of memory to use (in megabytes) when generating
candidate moduli for DH-GEX.
.It Fl m Ar key_format
-Specify a key format for the
+Specify a key format for key generation, the
.Fl i
-(import) or
+(import),
.Fl e
-(export) conversion options.
+(export) conversion options, and the
+.Fl p
+change passphrase operation.
+The latter may be used to convert between OpenSSH private key and PEM
+private key formats.
The supported key formats are:
.Dq RFC4716
(RFC 4716/SSH2 public or private key),
.Dq PKCS8
(PEM PKCS8 public key)
or
.Dq PEM
(PEM public key).
The default conversion format is
.Dq RFC4716 .
Setting a format of
.Dq PEM
when generating or updating a supported private key type will cause the
key to be stored in the legacy PEM private key format.
.It Fl N Ar new_passphrase
Provides the new passphrase.
.It Fl n Ar principals
Specify one or more principals (user or host names) to be included in
a certificate when signing a key.
Multiple principals may be specified, separated by commas.
Please see the
.Sx CERTIFICATES
section for details.
.It Fl O Ar option
Specify a certificate option when signing a key.
This option may be specified multiple times.
See also the
.Sx CERTIFICATES
section for further details.
.Pp
At present, no standard options are valid for host keys.
The options that are valid for user certificates are:
.Pp
.Bl -tag -width Ds -compact
.It Ic clear
Clear all enabled permissions.
This is useful for clearing the default set of permissions so permissions may
be added individually.
.Pp
.It Ic critical : Ns Ar name Ns Op Ns = Ns Ar contents
.It Ic extension : Ns Ar name Ns Op Ns = Ns Ar contents
Includes an arbitrary certificate critical option or extension.
The specified
.Ar name
should include a domain suffix, e.g.\&
.Dq name@example.com .
If
.Ar contents
is specified then it is included as the contents of the extension/option
encoded as a string, otherwise the extension/option is created with no
contents (usually indicating a flag).
Extensions may be ignored by a client or server that does not recognise them,
whereas unknown critical options will cause the certificate to be refused.
.Pp
.It Ic force-command Ns = Ns Ar command
Forces the execution of
.Ar command
instead of any shell or command specified by the user when
the certificate is used for authentication.
.Pp
.It Ic no-agent-forwarding
Disable
.Xr ssh-agent 1
forwarding (permitted by default).
.Pp
.It Ic no-port-forwarding
Disable port forwarding (permitted by default).
.Pp
.It Ic no-pty
Disable PTY allocation (permitted by default).
.Pp
.It Ic no-user-rc
Disable execution of
.Pa ~/.ssh/rc
by
.Xr sshd 8
(permitted by default).
.Pp
.It Ic no-x11-forwarding
Disable X11 forwarding (permitted by default).
.Pp
.It Ic permit-agent-forwarding
Allows
.Xr ssh-agent 1
forwarding.
.Pp
.It Ic permit-port-forwarding
Allows port forwarding.
.Pp
.It Ic permit-pty
Allows PTY allocation.
.Pp
.It Ic permit-user-rc
Allows execution of
.Pa ~/.ssh/rc
by
.Xr sshd 8 .
.Pp
.It Ic permit-X11-forwarding
Allows X11 forwarding.
.Pp
.It Ic source-address Ns = Ns Ar address_list
Restrict the source addresses from which the certificate is considered valid.
The
.Ar address_list
is a comma-separated list of one or more address/netmask pairs in CIDR
format.
.El
.It Fl P Ar passphrase
Provides the (old) passphrase.
.It Fl p
Requests changing the passphrase of a private key file instead of
creating a new private key.
The program will prompt for the file
containing the private key, for the old passphrase, and twice for the
new passphrase.
.It Fl Q
Test whether keys have been revoked in a KRL.
.It Fl q
Silence
.Nm ssh-keygen .
-.It Fl R Ar hostname
-Removes all keys belonging to
+.It Fl R Ar hostname | [hostname]:port
+Removes all keys belonging to the specified
.Ar hostname
+(with optional port number)
from a
.Pa known_hosts
file.
This option is useful to delete hashed hosts (see the
.Fl H
option above).
.It Fl r Ar hostname
Print the SSHFP fingerprint resource record named
.Ar hostname
for the specified public key file.
.It Fl S Ar start
Specify start point (in hex) when generating candidate moduli for DH-GEX.
.It Fl s Ar ca_key
Certify (sign) a public key using the specified CA key.
Please see the
.Sx CERTIFICATES
section for details.
.Pp
When generating a KRL,
.Fl s
specifies a path to a CA public key file used to revoke certificates directly
by key ID or serial number.
See the
.Sx KEY REVOCATION LISTS
section for details.
.It Fl T Ar output_file
Test DH group exchange candidate primes (generated using the
.Fl G
option) for safety.
.It Fl t Cm dsa | ecdsa | ed25519 | rsa
Specifies the type of key to create.
The possible values are
.Dq dsa ,
.Dq ecdsa ,
.Dq ed25519 ,
or
.Dq rsa .
.It Fl U
When used in combination with
.Fl s ,
this option indicates that a CA key resides in a
.Xr ssh-agent 1 .
See the
.Sx CERTIFICATES
section for more information.
.It Fl u
Update a KRL.
When specified with
.Fl k ,
keys listed via the command line are added to the existing KRL rather than
a new KRL being created.
.It Fl V Ar validity_interval
Specify a validity interval when signing a certificate.
A validity interval may consist of a single time, indicating that the
certificate is valid beginning now and expiring at that time, or may consist
of two times separated by a colon to indicate an explicit time interval.
.Pp
The start time may be specified as the string
.Dq always
to indicate the certificate has no specified start time,
a date in YYYYMMDD format, a time in YYYYMMDDHHMM[SS] format,
a relative time (to the current time) consisting of a minus sign followed by
an interval in the format described in the
TIME FORMATS section of
.Xr sshd_config 5 .
.Pp
The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMM[SS] time,
a relative time starting with a plus character or the string
.Dq forever
to indicate that the certificate has no expirty date.
.Pp
For example:
.Dq +52w1d
(valid from now to 52 weeks and one day from now),
.Dq -4w:+4w
(valid from four weeks ago to four weeks from now),
.Dq 20100101123000:20110101123000
(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
.Dq -1d:20110101
(valid from yesterday to midnight, January 1st, 2011).
.Dq -1m:forever
(valid from one minute ago and never expiring).
.It Fl v
Verbose mode.
Causes
.Nm
to print debugging messages about its progress.
This is helpful for debugging moduli generation.
Multiple
.Fl v
options increase the verbosity.
The maximum is 3.
.It Fl W Ar generator
Specify desired generator when testing candidate moduli for DH-GEX.
.It Fl y
This option will read a private
OpenSSH format file and print an OpenSSH public key to stdout.
.It Fl z Ar serial_number
Specifies a serial number to be embedded in the certificate to distinguish
this certificate from others from the same CA.
+If the
+.Ar serial_number
+is prefixed with a
+.Sq +
+character, then the serial number will be incremented for each certificate
+signed on a single command-line.
The default serial number is zero.
.Pp
When generating a KRL, the
.Fl z
flag is used to specify a KRL version number.
.El
.Sh MODULI GENERATION
.Nm
may be used to generate groups for the Diffie-Hellman Group Exchange
(DH-GEX) protocol.
Generating these groups is a two-step process: first, candidate
primes are generated using a fast, but memory intensive process.
These candidate primes are then tested for suitability (a CPU-intensive
process).
.Pp
Generation of primes is performed using the
.Fl G
option.
The desired length of the primes may be specified by the
.Fl b
option.
For example:
.Pp
.Dl # ssh-keygen -G moduli-2048.candidates -b 2048
.Pp
By default, the search for primes begins at a random point in the
desired length range.
This may be overridden using the
.Fl S
option, which specifies a different start point (in hex).
.Pp
Once a set of candidates have been generated, they must be screened for
suitability.
This may be performed using the
.Fl T
option.
In this mode
.Nm
will read candidates from standard input (or a file specified using the
.Fl f
option).
For example:
.Pp
.Dl # ssh-keygen -T moduli-2048 -f moduli-2048.candidates
.Pp
By default, each candidate will be subjected to 100 primality tests.
This may be overridden using the
.Fl a
option.
The DH generator value will be chosen automatically for the
prime under consideration.
If a specific generator is desired, it may be requested using the
.Fl W
option.
Valid generator values are 2, 3, and 5.
.Pp
Screened DH groups may be installed in
.Pa /etc/moduli .
It is important that this file contains moduli of a range of bit lengths and
that both ends of a connection share common moduli.
.Sh CERTIFICATES
.Nm
supports signing of keys to produce certificates that may be used for
user or host authentication.
Certificates consist of a public key, some identity information, zero or
more principal (user or host) names and a set of options that
are signed by a Certification Authority (CA) key.
Clients or servers may then trust only the CA key and verify its signature
on a certificate rather than trusting many user/host keys.
Note that OpenSSH certificates are a different, and much simpler, format to
the X.509 certificates used in
.Xr ssl 8 .
.Pp
.Nm
supports two types of certificates: user and host.
User certificates authenticate users to servers, whereas host certificates
authenticate server hosts to users.
To generate a user certificate:
.Pp
.Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub
.Pp
The resultant certificate will be placed in
.Pa /path/to/user_key-cert.pub .
A host certificate requires the
.Fl h
option:
.Pp
.Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub
.Pp
The host certificate will be output to
.Pa /path/to/host_key-cert.pub .
.Pp
It is possible to sign using a CA key stored in a PKCS#11 token by
providing the token library using
.Fl D
and identifying the CA key by providing its public half as an argument
to
.Fl s :
.Pp
.Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub
.Pp
Similarly, it is possible for the CA key to be hosted in a
.Xr ssh-agent 1 .
This is indicated by the
.Fl U
flag and, again, the CA key must be identified by its public half.
.Pp
.Dl $ ssh-keygen -Us ca_key.pub -I key_id user_key.pub
.Pp
In all cases,
.Ar key_id
is a "key identifier" that is logged by the server when the certificate
is used for authentication.
.Pp
Certificates may be limited to be valid for a set of principal (user/host)
names.
By default, generated certificates are valid for all users or hosts.
To generate a certificate for a specified set of principals:
.Pp
.Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub
.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain host_key.pub"
.Pp
Additional limitations on the validity and use of user certificates may
be specified through certificate options.
A certificate option may disable features of the SSH session, may be
valid only when presented from particular source addresses or may
force the use of a specific command.
For a list of valid certificate options, see the documentation for the
.Fl O
option above.
.Pp
Finally, certificates may be defined with a validity lifetime.
The
.Fl V
option allows specification of certificate start and end times.
A certificate that is presented at a time outside this range will not be
considered valid.
By default, certificates are valid from
.Ux
Epoch to the distant future.
.Pp
For certificates to be used for user or host authentication, the CA
public key must be trusted by
.Xr sshd 8
or
.Xr ssh 1 .
Please refer to those manual pages for details.
.Sh KEY REVOCATION LISTS
.Nm
is able to manage OpenSSH format Key Revocation Lists (KRLs).
These binary files specify keys or certificates to be revoked using a
compact format, taking as little as one bit per certificate if they are being
revoked by serial number.
.Pp
KRLs may be generated using the
.Fl k
flag.
This option reads one or more files from the command line and generates a new
KRL.
The files may either contain a KRL specification (see below) or public keys,
listed one per line.
Plain public keys are revoked by listing their hash or contents in the KRL and
certificates revoked by serial number or key ID (if the serial is zero or
not available).
.Pp
Revoking keys using a KRL specification offers explicit control over the
types of record used to revoke keys and may be used to directly revoke
certificates by serial number or key ID without having the complete original
certificate on hand.
A KRL specification consists of lines containing one of the following directives
followed by a colon and some directive-specific information.
.Bl -tag -width Ds
.It Cm serial : Ar serial_number Ns Op - Ns Ar serial_number
Revokes a certificate with the specified serial number.
Serial numbers are 64-bit values, not including zero and may be expressed
in decimal, hex or octal.
If two serial numbers are specified separated by a hyphen, then the range
of serial numbers including and between each is revoked.
The CA key must have been specified on the
.Nm
command line using the
.Fl s
option.
.It Cm id : Ar key_id
Revokes a certificate with the specified key ID string.
The CA key must have been specified on the
.Nm
command line using the
.Fl s
option.
.It Cm key : Ar public_key
Revokes the specified key.
If a certificate is listed, then it is revoked as a plain public key.
.It Cm sha1 : Ar public_key
Revokes the specified key by including its SHA1 hash in the KRL.
.It Cm sha256 : Ar public_key
Revokes the specified key by including its SHA256 hash in the KRL.
KRLs that revoke keys by SHA256 hash are not supported by OpenSSH versions
prior to 7.9.
.It Cm hash : Ar fingerprint
Revokes a key using a fingerprint hash, as obtained from a
.Xr sshd 8
authentication log message or the
.Nm
.Fl l
flag.
Only SHA256 fingerprints are supported here and resultant KRLs are
not supported by OpenSSH versions prior to 7.9.
.El
.Pp
KRLs may be updated using the
.Fl u
flag in addition to
.Fl k .
When this option is specified, keys listed via the command line are merged into
the KRL, adding to those already there.
.Pp
It is also possible, given a KRL, to test whether it revokes a particular key
(or keys).
The
.Fl Q
flag will query an existing KRL, testing each key specified on the command line.
If any key listed on the command line has been revoked (or an error encountered)
then
.Nm
will exit with a non-zero exit status.
A zero exit status will only be returned if no key was revoked.
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.ssh/id_dsa
.It Pa ~/.ssh/id_ecdsa
.It Pa ~/.ssh/id_ed25519
.It Pa ~/.ssh/id_rsa
Contains the DSA, ECDSA, Ed25519 or RSA
authentication identity of the user.
This file should not be readable by anyone but the user.
It is possible to
specify a passphrase when generating the key; that passphrase will be
used to encrypt the private part of this file using 128-bit AES.
This file is not automatically accessed by
.Nm
but it is offered as the default file for the private key.
.Xr ssh 1
will read this file when a login attempt is made.
.Pp
.It Pa ~/.ssh/id_dsa.pub
.It Pa ~/.ssh/id_ecdsa.pub
.It Pa ~/.ssh/id_ed25519.pub
.It Pa ~/.ssh/id_rsa.pub
Contains the DSA, ECDSA, Ed25519 or RSA
public key for authentication.
The contents of this file should be added to
.Pa ~/.ssh/authorized_keys
on all machines
where the user wishes to log in using public key authentication.
There is no need to keep the contents of this file secret.
.Pp
.It Pa /etc/moduli
Contains Diffie-Hellman groups used for DH-GEX.
The file format is described in
.Xr moduli 5 .
.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr moduli 5 ,
.Xr sshd 8
.Rs
.%R RFC 4716
.%T "The Secure Shell (SSH) Public Key File Format"
.%D 2006
.Re
.Sh AUTHORS
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by Tatu Ylonen.
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
Theo de Raadt and Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 46b3af5a89ed..3898b281e5a0 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,2945 +1,2953 @@
-/* $OpenBSD: ssh-keygen.c,v 1.322 2018/09/14 04:17:44 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.329 2019/03/25 16:19:44 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Identity and host key generation and maintenance.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "openbsd-compat/openssl-compat.h"
#endif
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <locale.h>
#include <time.h>
#include "xmalloc.h"
#include "sshkey.h"
#include "authfile.h"
#include "uuencode.h"
#include "sshbuf.h"
#include "pathnames.h"
#include "log.h"
#include "misc.h"
#include "match.h"
#include "hostfile.h"
#include "dns.h"
#include "ssh.h"
#include "ssh2.h"
#include "ssherr.h"
#include "ssh-pkcs11.h"
#include "atomicio.h"
#include "krl.h"
#include "digest.h"
#include "utf8.h"
#include "authfd.h"
#ifdef WITH_OPENSSL
# define DEFAULT_KEY_TYPE_NAME "rsa"
#else
# define DEFAULT_KEY_TYPE_NAME "ed25519"
#endif
-/* Number of bits in the RSA/DSA key. This value can be set on the command line. */
-#define DEFAULT_BITS 2048
-#define DEFAULT_BITS_DSA 1024
-#define DEFAULT_BITS_ECDSA 256
-u_int32_t bits = 0;
-
/*
- * Flag indicating that we just want to change the passphrase. This can be
- * set on the command line.
- */
-int change_passphrase = 0;
-
-/*
- * Flag indicating that we just want to change the comment. This can be set
- * on the command line.
+ * Default number of bits in the RSA, DSA and ECDSA keys. These value can be
+ * overridden on the command line.
+ *
+ * These values, with the exception of DSA, provide security equivalent to at
+ * least 128 bits of security according to NIST Special Publication 800-57:
+ * Recommendation for Key Management Part 1 rev 4 section 5.6.1.
+ * For DSA it (and FIPS-186-4 section 4.2) specifies that the only size for
+ * which a 160bit hash is acceptable is 1kbit, and since ssh-dss specifies only
+ * SHA1 we limit the DSA key size 1k bits.
*/
-int change_comment = 0;
-
-int quiet = 0;
-
-int log_level = SYSLOG_LEVEL_INFO;
-
-/* Flag indicating that we want to hash a known_hosts file */
-int hash_hosts = 0;
-/* Flag indicating that we want lookup a host in known_hosts file */
-int find_host = 0;
-/* Flag indicating that we want to delete a host from a known_hosts file */
-int delete_host = 0;
+#define DEFAULT_BITS 3072
+#define DEFAULT_BITS_DSA 1024
+#define DEFAULT_BITS_ECDSA 256
-/* Flag indicating that we want to show the contents of a certificate */
-int show_cert = 0;
+static int quiet = 0;
/* Flag indicating that we just want to see the key fingerprint */
-int print_fingerprint = 0;
-int print_bubblebabble = 0;
+static int print_fingerprint = 0;
+static int print_bubblebabble = 0;
/* Hash algorithm to use for fingerprints. */
-int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* The identity file name, given on the command line or entered by the user. */
-char identity_file[1024];
-int have_identity = 0;
+static char identity_file[1024];
+static int have_identity = 0;
/* This is set to the passphrase if given on the command line. */
-char *identity_passphrase = NULL;
+static char *identity_passphrase = NULL;
/* This is set to the new passphrase if given on the command line. */
-char *identity_new_passphrase = NULL;
-
-/* This is set to the new comment if given on the command line. */
-char *identity_comment = NULL;
-
-/* Path to CA key when certifying keys. */
-char *ca_key_path = NULL;
-
-/* Prefer to use agent keys for CA signing */
-int prefer_agent = 0;
-
-/* Certificate serial number */
-unsigned long long cert_serial = 0;
+static char *identity_new_passphrase = NULL;
/* Key type when certifying */
-u_int cert_key_type = SSH2_CERT_TYPE_USER;
+static u_int cert_key_type = SSH2_CERT_TYPE_USER;
/* "key ID" of signed key */
-char *cert_key_id = NULL;
+static char *cert_key_id = NULL;
/* Comma-separated list of principal names for certifying keys */
-char *cert_principals = NULL;
+static char *cert_principals = NULL;
/* Validity period for certificates */
-u_int64_t cert_valid_from = 0;
-u_int64_t cert_valid_to = ~0ULL;
+static u_int64_t cert_valid_from = 0;
+static u_int64_t cert_valid_to = ~0ULL;
/* Certificate options */
#define CERTOPT_X_FWD (1)
#define CERTOPT_AGENT_FWD (1<<1)
#define CERTOPT_PORT_FWD (1<<2)
#define CERTOPT_PTY (1<<3)
#define CERTOPT_USER_RC (1<<4)
#define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \
CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC)
-u_int32_t certflags_flags = CERTOPT_DEFAULT;
-char *certflags_command = NULL;
-char *certflags_src_addr = NULL;
+static u_int32_t certflags_flags = CERTOPT_DEFAULT;
+static char *certflags_command = NULL;
+static char *certflags_src_addr = NULL;
/* Arbitrary extensions specified by user */
struct cert_userext {
char *key;
char *val;
int crit;
};
-struct cert_userext *cert_userext;
-size_t ncert_userext;
+static struct cert_userext *cert_userext;
+static size_t ncert_userext;
/* Conversion to/from various formats */
-int convert_to = 0;
-int convert_from = 0;
enum {
FMT_RFC4716,
FMT_PKCS8,
FMT_PEM
} convert_format = FMT_RFC4716;
-int print_public = 0;
-int print_generic = 0;
-char *key_type_name = NULL;
+static char *key_type_name = NULL;
/* Load key from this PKCS#11 provider */
-char *pkcs11provider = NULL;
+static char *pkcs11provider = NULL;
/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
-int use_new_format = 1;
+static int use_new_format = 1;
/* Cipher for new-format private keys */
-char *new_format_cipher = NULL;
+static char *new_format_cipher = NULL;
/*
* Number of KDF rounds to derive new format keys /
* number of primality trials when screening moduli.
*/
-int rounds = 0;
+static int rounds = 0;
/* argv0 */
extern char *__progname;
-char hostname[NI_MAXHOST];
+static char hostname[NI_MAXHOST];
#ifdef WITH_OPENSSL
/* moduli.c */
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long,
unsigned long);
#endif
static void
type_bits_valid(int type, const char *name, u_int32_t *bitsp)
{
#ifdef WITH_OPENSSL
u_int maxbits, nid;
#endif
if (type == KEY_UNSPEC)
fatal("unknown key type %s", key_type_name);
if (*bitsp == 0) {
#ifdef WITH_OPENSSL
if (type == KEY_DSA)
*bitsp = DEFAULT_BITS_DSA;
else if (type == KEY_ECDSA) {
if (name != NULL &&
(nid = sshkey_ecdsa_nid_from_name(name)) > 0)
*bitsp = sshkey_curve_nid_to_bits(nid);
if (*bitsp == 0)
*bitsp = DEFAULT_BITS_ECDSA;
} else
#endif
*bitsp = DEFAULT_BITS;
}
#ifdef WITH_OPENSSL
maxbits = (type == KEY_DSA) ?
OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
if (*bitsp > maxbits)
fatal("key bits exceeds maximum %d", maxbits);
switch (type) {
case KEY_DSA:
if (*bitsp != 1024)
fatal("Invalid DSA key length: must be 1024 bits");
break;
case KEY_RSA:
if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE)
fatal("Invalid RSA key length: minimum is %d bits",
SSH_RSA_MINIMUM_MODULUS_SIZE);
break;
case KEY_ECDSA:
if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
fatal("Invalid ECDSA key length: valid lengths are "
+#ifdef OPENSSL_HAS_NISTP521
"256, 384 or 521 bits");
+#else
+ "256 or 384 bits");
+#endif
}
#endif
}
static void
ask_filename(struct passwd *pw, const char *prompt)
{
char buf[1024];
char *name = NULL;
if (key_type_name == NULL)
name = _PATH_SSH_CLIENT_ID_RSA;
else {
switch (sshkey_type_from_name(key_type_name)) {
case KEY_DSA_CERT:
case KEY_DSA:
name = _PATH_SSH_CLIENT_ID_DSA;
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
case KEY_ECDSA:
name = _PATH_SSH_CLIENT_ID_ECDSA;
break;
#endif
case KEY_RSA_CERT:
case KEY_RSA:
name = _PATH_SSH_CLIENT_ID_RSA;
break;
case KEY_ED25519:
case KEY_ED25519_CERT:
name = _PATH_SSH_CLIENT_ID_ED25519;
break;
case KEY_XMSS:
case KEY_XMSS_CERT:
name = _PATH_SSH_CLIENT_ID_XMSS;
break;
default:
fatal("bad key type");
}
}
snprintf(identity_file, sizeof(identity_file),
"%s/%s", pw->pw_dir, name);
printf("%s (%s): ", prompt, identity_file);
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
exit(1);
buf[strcspn(buf, "\n")] = '\0';
if (strcmp(buf, "") != 0)
strlcpy(identity_file, buf, sizeof(identity_file));
have_identity = 1;
}
static struct sshkey *
load_identity(char *filename)
{
char *pass;
struct sshkey *prv;
int r;
if ((r = sshkey_load_private(filename, "", &prv, NULL)) == 0)
return prv;
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
fatal("Load key \"%s\": %s", filename, ssh_err(r));
if (identity_passphrase)
pass = xstrdup(identity_passphrase);
else
pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN);
r = sshkey_load_private(filename, pass, &prv, NULL);
explicit_bzero(pass, strlen(pass));
free(pass);
if (r != 0)
fatal("Load key \"%s\": %s", filename, ssh_err(r));
return prv;
}
#define SSH_COM_PUBLIC_BEGIN "---- BEGIN SSH2 PUBLIC KEY ----"
#define SSH_COM_PUBLIC_END "---- END SSH2 PUBLIC KEY ----"
#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
#ifdef WITH_OPENSSL
static void
do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
{
size_t len;
u_char *blob;
char comment[61];
int r;
if ((r = sshkey_to_blob(k, &blob, &len)) != 0)
fatal("key_to_blob failed: %s", ssh_err(r));
/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
snprintf(comment, sizeof(comment),
"%u-bit %s, converted by %s@%s from OpenSSH",
sshkey_size(k), sshkey_type(k),
pw->pw_name, hostname);
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
fprintf(stdout, "Comment: \"%s\"\n", comment);
dump_base64(stdout, blob, len);
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
sshkey_free(k);
free(blob);
exit(0);
}
static void
do_convert_to_pkcs8(struct sshkey *k)
{
switch (sshkey_type_plain(k->type)) {
case KEY_RSA:
if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
fatal("PEM_write_RSA_PUBKEY failed");
break;
case KEY_DSA:
if (!PEM_write_DSA_PUBKEY(stdout, k->dsa))
fatal("PEM_write_DSA_PUBKEY failed");
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa))
fatal("PEM_write_EC_PUBKEY failed");
break;
#endif
default:
fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
}
exit(0);
}
static void
do_convert_to_pem(struct sshkey *k)
{
switch (sshkey_type_plain(k->type)) {
case KEY_RSA:
if (!PEM_write_RSAPublicKey(stdout, k->rsa))
fatal("PEM_write_RSAPublicKey failed");
break;
default:
fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
}
exit(0);
}
static void
do_convert_to(struct passwd *pw)
{
struct sshkey *k;
struct stat st;
int r;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0)
k = load_identity(identity_file);
switch (convert_format) {
case FMT_RFC4716:
do_convert_to_ssh2(pw, k);
break;
case FMT_PKCS8:
do_convert_to_pkcs8(k);
break;
case FMT_PEM:
do_convert_to_pem(k);
break;
default:
fatal("%s: unknown key format %d", __func__, convert_format);
}
exit(0);
}
/*
* This is almost exactly the bignum1 encoding, but with 32 bit for length
* instead of 16.
*/
static void
buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
{
u_int bytes, bignum_bits;
int r;
if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
bytes = (bignum_bits + 7) / 8;
if (sshbuf_len(b) < bytes)
fatal("%s: input buffer too small: need %d have %zu",
__func__, bytes, sshbuf_len(b));
if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL)
fatal("%s: BN_bin2bn failed", __func__);
if ((r = sshbuf_consume(b, bytes)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
static struct sshkey *
do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
{
struct sshbuf *b;
struct sshkey *key = NULL;
char *type, *cipher;
u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345";
int r, rlen, ktype;
u_int magic, i1, i2, i3, i4;
size_t slen;
u_long e;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
if ((b = sshbuf_from(blob, blen)) == NULL)
fatal("%s: sshbuf_from failed", __func__);
if ((r = sshbuf_get_u32(b, &magic)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
error("bad magic 0x%x != 0x%x", magic,
SSH_COM_PRIVATE_KEY_MAGIC);
sshbuf_free(b);
return NULL;
}
if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
(r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
(r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 ||
(r = sshbuf_get_u32(b, &i2)) != 0 ||
(r = sshbuf_get_u32(b, &i3)) != 0 ||
(r = sshbuf_get_u32(b, &i4)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
if (strcmp(cipher, "none") != 0) {
error("unsupported cipher %s", cipher);
free(cipher);
sshbuf_free(b);
free(type);
return NULL;
}
free(cipher);
if (strstr(type, "dsa")) {
ktype = KEY_DSA;
} else if (strstr(type, "rsa")) {
ktype = KEY_RSA;
} else {
sshbuf_free(b);
free(type);
return NULL;
}
if ((key = sshkey_new(ktype)) == NULL)
fatal("sshkey_new failed");
free(type);
switch (key->type) {
case KEY_DSA:
if ((dsa_p = BN_new()) == NULL ||
(dsa_q = BN_new()) == NULL ||
(dsa_g = BN_new()) == NULL ||
(dsa_pub_key = BN_new()) == NULL ||
(dsa_priv_key = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
buffer_get_bignum_bits(b, dsa_p);
buffer_get_bignum_bits(b, dsa_g);
buffer_get_bignum_bits(b, dsa_q);
buffer_get_bignum_bits(b, dsa_pub_key);
buffer_get_bignum_bits(b, dsa_priv_key);
if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g))
fatal("%s: DSA_set0_pqg failed", __func__);
dsa_p = dsa_q = dsa_g = NULL; /* transferred */
if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key))
fatal("%s: DSA_set0_key failed", __func__);
dsa_pub_key = dsa_priv_key = NULL; /* transferred */
break;
case KEY_RSA:
if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
(e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
(e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
fatal("%s: buffer error: %s", __func__, ssh_err(r));
e = e1;
debug("e %lx", e);
if (e < 30) {
e <<= 8;
e += e2;
debug("e %lx", e);
e <<= 8;
e += e3;
debug("e %lx", e);
}
if ((rsa_e = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
if (!BN_set_word(rsa_e, e)) {
BN_clear_free(rsa_e);
sshbuf_free(b);
sshkey_free(key);
return NULL;
}
if ((rsa_n = BN_new()) == NULL ||
(rsa_d = BN_new()) == NULL ||
(rsa_p = BN_new()) == NULL ||
(rsa_q = BN_new()) == NULL ||
(rsa_iqmp = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
buffer_get_bignum_bits(b, rsa_d);
buffer_get_bignum_bits(b, rsa_n);
buffer_get_bignum_bits(b, rsa_iqmp);
buffer_get_bignum_bits(b, rsa_q);
buffer_get_bignum_bits(b, rsa_p);
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d))
fatal("%s: RSA_set0_key failed", __func__);
rsa_n = rsa_e = rsa_d = NULL; /* transferred */
if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q))
fatal("%s: RSA_set0_factors failed", __func__);
rsa_p = rsa_q = NULL; /* transferred */
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
fatal("generate RSA parameters failed: %s", ssh_err(r));
BN_clear_free(rsa_iqmp);
break;
}
rlen = sshbuf_len(b);
if (rlen != 0)
error("do_convert_private_ssh2_from_blob: "
"remaining bytes in key blob %d", rlen);
sshbuf_free(b);
/* try the key */
if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 ||
sshkey_verify(key, sig, slen, data, sizeof(data), NULL, 0) != 0) {
sshkey_free(key);
free(sig);
return NULL;
}
free(sig);
return key;
}
static int
get_line(FILE *fp, char *line, size_t len)
{
int c;
size_t pos = 0;
line[0] = '\0';
while ((c = fgetc(fp)) != EOF) {
if (pos >= len - 1)
fatal("input line too long.");
switch (c) {
case '\r':
c = fgetc(fp);
if (c != EOF && c != '\n' && ungetc(c, fp) == EOF)
fatal("unget: %s", strerror(errno));
return pos;
case '\n':
return pos;
}
line[pos++] = c;
line[pos] = '\0';
}
/* We reached EOF */
return -1;
}
static void
do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
{
int r, blen, escaped = 0;
u_int len;
char line[1024];
u_char blob[8096];
char encoded[8096];
FILE *fp;
if ((fp = fopen(identity_file, "r")) == NULL)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
encoded[0] = '\0';
while ((blen = get_line(fp, line, sizeof(line))) != -1) {
if (blen > 0 && line[blen - 1] == '\\')
escaped++;
if (strncmp(line, "----", 4) == 0 ||
strstr(line, ": ") != NULL) {
if (strstr(line, SSH_COM_PRIVATE_BEGIN) != NULL)
*private = 1;
if (strstr(line, " END ") != NULL) {
break;
}
/* fprintf(stderr, "ignore: %s", line); */
continue;
}
if (escaped) {
escaped--;
/* fprintf(stderr, "escaped: %s", line); */
continue;
}
strlcat(encoded, line, sizeof(encoded));
}
len = strlen(encoded);
if (((len % 4) == 3) &&
(encoded[len-1] == '=') &&
(encoded[len-2] == '=') &&
(encoded[len-3] == '='))
encoded[len-3] = '\0';
blen = uudecode(encoded, blob, sizeof(blob));
if (blen < 0)
fatal("uudecode failed.");
if (*private)
*k = do_convert_private_ssh2_from_blob(blob, blen);
else if ((r = sshkey_from_blob(blob, blen, k)) != 0)
fatal("decode blob failed: %s", ssh_err(r));
fclose(fp);
}
static void
do_convert_from_pkcs8(struct sshkey **k, int *private)
{
EVP_PKEY *pubkey;
FILE *fp;
if ((fp = fopen(identity_file, "r")) == NULL)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
fatal("%s: %s is not a recognised public key format", __func__,
identity_file);
}
fclose(fp);
switch (EVP_PKEY_base_id(pubkey)) {
case EVP_PKEY_RSA:
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed");
(*k)->type = KEY_RSA;
(*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
break;
case EVP_PKEY_DSA:
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed");
(*k)->type = KEY_DSA;
(*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
break;
#ifdef OPENSSL_HAS_ECC
case EVP_PKEY_EC:
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed");
(*k)->type = KEY_ECDSA;
(*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
(*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa);
break;
#endif
default:
fatal("%s: unsupported pubkey type %d", __func__,
EVP_PKEY_base_id(pubkey));
}
EVP_PKEY_free(pubkey);
return;
}
static void
do_convert_from_pem(struct sshkey **k, int *private)
{
FILE *fp;
RSA *rsa;
if ((fp = fopen(identity_file, "r")) == NULL)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed");
(*k)->type = KEY_RSA;
(*k)->rsa = rsa;
fclose(fp);
return;
}
fatal("%s: unrecognised raw private key format", __func__);
}
static void
do_convert_from(struct passwd *pw)
{
struct sshkey *k = NULL;
int r, private = 0, ok = 0;
struct stat st;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
switch (convert_format) {
case FMT_RFC4716:
do_convert_from_ssh2(pw, &k, &private);
break;
case FMT_PKCS8:
do_convert_from_pkcs8(&k, &private);
break;
case FMT_PEM:
do_convert_from_pem(&k, &private);
break;
default:
fatal("%s: unknown key format %d", __func__, convert_format);
}
if (!private) {
if ((r = sshkey_write(k, stdout)) == 0)
ok = 1;
if (ok)
fprintf(stdout, "\n");
} else {
switch (k->type) {
case KEY_DSA:
ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL,
NULL, 0, NULL, NULL);
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL,
NULL, 0, NULL, NULL);
break;
#endif
case KEY_RSA:
ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL,
NULL, 0, NULL, NULL);
break;
default:
fatal("%s: unsupported key type %s", __func__,
sshkey_type(k));
}
}
if (!ok)
fatal("key write failed");
sshkey_free(k);
exit(0);
}
#endif
static void
do_print_public(struct passwd *pw)
{
struct sshkey *prv;
struct stat st;
int r;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0)
fatal("%s: %s", identity_file, strerror(errno));
prv = load_identity(identity_file);
if ((r = sshkey_write(prv, stdout)) != 0)
error("sshkey_write failed: %s", ssh_err(r));
sshkey_free(prv);
fprintf(stdout, "\n");
exit(0);
}
static void
do_download(struct passwd *pw)
{
#ifdef ENABLE_PKCS11
struct sshkey **keys = NULL;
int i, nkeys;
enum sshkey_fp_rep rep;
int fptype;
char *fp, *ra;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
- pkcs11_init(0);
+ pkcs11_init(1);
nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
for (i = 0; i < nkeys; i++) {
if (print_fingerprint) {
fp = sshkey_fingerprint(keys[i], fptype, rep);
ra = sshkey_fingerprint(keys[i], fingerprint_hash,
SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
fp, sshkey_type(keys[i]));
- if (log_level >= SYSLOG_LEVEL_VERBOSE)
+ if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
free(ra);
free(fp);
} else {
(void) sshkey_write(keys[i], stdout); /* XXX check */
fprintf(stdout, "\n");
}
sshkey_free(keys[i]);
}
free(keys);
pkcs11_terminate();
exit(0);
#else
fatal("no pkcs11 support");
#endif /* ENABLE_PKCS11 */
}
static struct sshkey *
try_read_key(char **cpp)
{
struct sshkey *ret;
int r;
if ((ret = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new failed");
if ((r = sshkey_read(ret, cpp)) == 0)
return ret;
/* Not a key */
sshkey_free(ret);
return NULL;
}
static void
fingerprint_one_key(const struct sshkey *public, const char *comment)
{
char *fp = NULL, *ra = NULL;
enum sshkey_fp_rep rep;
int fptype;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
fp = sshkey_fingerprint(public, fptype, rep);
ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
comment ? comment : "no comment", sshkey_type(public));
- if (log_level >= SYSLOG_LEVEL_VERBOSE)
+ if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
printf("%s\n", ra);
free(ra);
free(fp);
}
static void
fingerprint_private(const char *path)
{
struct stat st;
char *comment = NULL;
struct sshkey *public = NULL;
int r;
if (stat(identity_file, &st) < 0)
fatal("%s: %s", path, strerror(errno));
if ((r = sshkey_load_public(path, &public, &comment)) != 0) {
debug("load public \"%s\": %s", path, ssh_err(r));
if ((r = sshkey_load_private(path, NULL,
&public, &comment)) != 0) {
debug("load private \"%s\": %s", path, ssh_err(r));
fatal("%s is not a key file.", path);
}
}
fingerprint_one_key(public, comment);
sshkey_free(public);
free(comment);
}
static void
do_fingerprint(struct passwd *pw)
{
FILE *f;
struct sshkey *public = NULL;
char *comment = NULL, *cp, *ep, *line = NULL;
size_t linesize = 0;
int i, invalid = 1;
const char *path;
u_long lnum = 0;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
path = identity_file;
if (strcmp(identity_file, "-") == 0) {
f = stdin;
path = "(stdin)";
} else if ((f = fopen(path, "r")) == NULL)
fatal("%s: %s: %s", __progname, path, strerror(errno));
while (getline(&line, &linesize, f) != -1) {
lnum++;
cp = line;
cp[strcspn(cp, "\n")] = '\0';
/* Trim leading space and comments */
cp = line + strspn(line, " \t");
if (*cp == '#' || *cp == '\0')
continue;
/*
* Input may be plain keys, private keys, authorized_keys
* or known_hosts.
*/
/*
* Try private keys first. Assume a key is private if
* "SSH PRIVATE KEY" appears on the first line and we're
* not reading from stdin (XXX support private keys on stdin).
*/
if (lnum == 1 && strcmp(identity_file, "-") != 0 &&
strstr(cp, "PRIVATE KEY") != NULL) {
free(line);
fclose(f);
fingerprint_private(path);
exit(0);
}
/*
* If it's not a private key, then this must be prepared to
* accept a public key prefixed with a hostname or options.
* Try a bare key first, otherwise skip the leading stuff.
*/
if ((public = try_read_key(&cp)) == NULL) {
i = strtol(cp, &ep, 10);
if (i == 0 || ep == NULL ||
(*ep != ' ' && *ep != '\t')) {
int quoted = 0;
comment = cp;
for (; *cp && (quoted || (*cp != ' ' &&
*cp != '\t')); cp++) {
if (*cp == '\\' && cp[1] == '"')
cp++; /* Skip both */
else if (*cp == '"')
quoted = !quoted;
}
if (!*cp)
continue;
*cp++ = '\0';
}
}
/* Retry after parsing leading hostname/key options */
if (public == NULL && (public = try_read_key(&cp)) == NULL) {
debug("%s:%lu: not a public key", path, lnum);
continue;
}
/* Find trailing comment, if any */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (*cp != '\0' && *cp != '#')
comment = cp;
fingerprint_one_key(public, comment);
sshkey_free(public);
invalid = 0; /* One good key in the file is sufficient */
}
fclose(f);
free(line);
if (invalid)
fatal("%s is not a public key file.", path);
exit(0);
}
static void
do_gen_all_hostkeys(struct passwd *pw)
{
struct {
char *key_type;
char *key_type_display;
char *path;
} key_types[] = {
#ifdef WITH_OPENSSL
{ "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
{ "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE },
#ifdef OPENSSL_HAS_ECC
{ "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
{ "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE },
#ifdef WITH_XMSS
{ "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE },
#endif /* WITH_XMSS */
{ NULL, NULL, NULL }
};
+ u_int bits = 0;
int first = 0;
struct stat st;
struct sshkey *private, *public;
char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
int i, type, fd, r;
FILE *f;
for (i = 0; key_types[i].key_type; i++) {
public = private = NULL;
prv_tmp = pub_tmp = prv_file = pub_file = NULL;
xasprintf(&prv_file, "%s%s",
identity_file, key_types[i].path);
/* Check whether private key exists and is not zero-length */
if (stat(prv_file, &st) == 0) {
if (st.st_size != 0)
goto next;
} else if (errno != ENOENT) {
error("Could not stat %s: %s", key_types[i].path,
strerror(errno));
goto failnext;
}
/*
* Private key doesn't exist or is invalid; proceed with
* key generation.
*/
xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
identity_file, key_types[i].path);
xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
identity_file, key_types[i].path);
xasprintf(&pub_file, "%s%s.pub",
identity_file, key_types[i].path);
if (first == 0) {
first = 1;
printf("%s: generating new host keys: ", __progname);
}
printf("%s ", key_types[i].key_type_display);
fflush(stdout);
type = sshkey_type_from_name(key_types[i].key_type);
if ((fd = mkstemp(prv_tmp)) == -1) {
error("Could not save your public key in %s: %s",
prv_tmp, strerror(errno));
goto failnext;
}
close(fd); /* just using mkstemp() to generate/reserve a name */
bits = 0;
type_bits_valid(type, NULL, &bits);
if ((r = sshkey_generate(type, bits, &private)) != 0) {
error("sshkey_generate failed: %s", ssh_err(r));
goto failnext;
}
if ((r = sshkey_from_private(private, &public)) != 0)
fatal("sshkey_from_private failed: %s", ssh_err(r));
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
hostname);
if ((r = sshkey_save_private(private, prv_tmp, "",
comment, use_new_format, new_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
prv_tmp, ssh_err(r));
goto failnext;
}
if ((fd = mkstemp(pub_tmp)) == -1) {
error("Could not save your public key in %s: %s",
pub_tmp, strerror(errno));
goto failnext;
}
(void)fchmod(fd, 0644);
f = fdopen(fd, "w");
if (f == NULL) {
error("fdopen %s failed: %s", pub_tmp, strerror(errno));
close(fd);
goto failnext;
}
if ((r = sshkey_write(public, f)) != 0) {
error("write key failed: %s", ssh_err(r));
fclose(f);
goto failnext;
}
fprintf(f, " %s\n", comment);
if (ferror(f) != 0) {
error("write key failed: %s", strerror(errno));
fclose(f);
goto failnext;
}
if (fclose(f) != 0) {
error("key close failed: %s", strerror(errno));
goto failnext;
}
/* Rename temporary files to their permanent locations. */
if (rename(pub_tmp, pub_file) != 0) {
error("Unable to move %s into position: %s",
pub_file, strerror(errno));
goto failnext;
}
if (rename(prv_tmp, prv_file) != 0) {
error("Unable to move %s into position: %s",
key_types[i].path, strerror(errno));
failnext:
first = 0;
goto next;
}
next:
sshkey_free(private);
sshkey_free(public);
free(prv_tmp);
free(pub_tmp);
free(prv_file);
free(pub_file);
}
if (first != 0)
printf("\n");
}
struct known_hosts_ctx {
const char *host; /* Hostname searched for in find/delete case */
FILE *out; /* Output file, stdout for find_hosts case */
int has_unhashed; /* When hashing, original had unhashed hosts */
int found_key; /* For find/delete, host was found */
int invalid; /* File contained invalid items; don't delete */
+ int hash_hosts; /* Hash hostnames as we go */
+ int find_host; /* Search for specific hostname */
+ int delete_host; /* Delete host from known_hosts */
};
static int
known_hosts_hash(struct hostkey_foreach_line *l, void *_ctx)
{
struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
char *hashed, *cp, *hosts, *ohosts;
int has_wild = l->hosts && strcspn(l->hosts, "*?!") != strlen(l->hosts);
int was_hashed = l->hosts && l->hosts[0] == HASH_DELIM;
switch (l->status) {
case HKF_STATUS_OK:
case HKF_STATUS_MATCHED:
/*
* Don't hash hosts already already hashed, with wildcard
* characters or a CA/revocation marker.
*/
if (was_hashed || has_wild || l->marker != MRK_NONE) {
fprintf(ctx->out, "%s\n", l->line);
- if (has_wild && !find_host) {
+ if (has_wild && !ctx->find_host) {
logit("%s:%lu: ignoring host name "
"with wildcard: %.64s", l->path,
l->linenum, l->hosts);
}
return 0;
}
/*
* Split any comma-separated hostnames from the host list,
* hash and store separately.
*/
ohosts = hosts = xstrdup(l->hosts);
while ((cp = strsep(&hosts, ",")) != NULL && *cp != '\0') {
lowercase(cp);
if ((hashed = host_hash(cp, NULL, 0)) == NULL)
fatal("hash_host failed");
fprintf(ctx->out, "%s %s\n", hashed, l->rawkey);
ctx->has_unhashed = 1;
}
free(ohosts);
return 0;
case HKF_STATUS_INVALID:
/* Retain invalid lines, but mark file as invalid. */
ctx->invalid = 1;
logit("%s:%lu: invalid line", l->path, l->linenum);
/* FALLTHROUGH */
default:
fprintf(ctx->out, "%s\n", l->line);
return 0;
}
/* NOTREACHED */
return -1;
}
static int
known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
{
struct known_hosts_ctx *ctx = (struct known_hosts_ctx *)_ctx;
enum sshkey_fp_rep rep;
int fptype;
char *fp;
fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash;
rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
if (l->status == HKF_STATUS_MATCHED) {
- if (delete_host) {
+ if (ctx->delete_host) {
if (l->marker != MRK_NONE) {
/* Don't remove CA and revocation lines */
fprintf(ctx->out, "%s\n", l->line);
} else {
/*
* Hostname matches and has no CA/revoke
* marker, delete it by *not* writing the
* line to ctx->out.
*/
ctx->found_key = 1;
if (!quiet)
printf("# Host %s found: line %lu\n",
ctx->host, l->linenum);
}
return 0;
- } else if (find_host) {
+ } else if (ctx->find_host) {
ctx->found_key = 1;
if (!quiet) {
printf("# Host %s found: line %lu %s\n",
ctx->host,
l->linenum, l->marker == MRK_CA ? "CA" :
(l->marker == MRK_REVOKE ? "REVOKED" : ""));
}
- if (hash_hosts)
+ if (ctx->hash_hosts)
known_hosts_hash(l, ctx);
else if (print_fingerprint) {
fp = sshkey_fingerprint(l->key, fptype, rep);
mprintf("%s %s %s %s\n", ctx->host,
sshkey_type(l->key), fp, l->comment);
free(fp);
} else
fprintf(ctx->out, "%s\n", l->line);
return 0;
}
- } else if (delete_host) {
+ } else if (ctx->delete_host) {
/* Retain non-matching hosts when deleting */
if (l->status == HKF_STATUS_INVALID) {
ctx->invalid = 1;
logit("%s:%lu: invalid line", l->path, l->linenum);
}
fprintf(ctx->out, "%s\n", l->line);
}
return 0;
}
static void
-do_known_hosts(struct passwd *pw, const char *name)
+do_known_hosts(struct passwd *pw, const char *name, int find_host,
+ int delete_host, int hash_hosts)
{
char *cp, tmp[PATH_MAX], old[PATH_MAX];
int r, fd, oerrno, inplace = 0;
struct known_hosts_ctx ctx;
u_int foreach_options;
if (!have_identity) {
cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
sizeof(identity_file))
fatal("Specified known hosts path too long");
free(cp);
have_identity = 1;
}
memset(&ctx, 0, sizeof(ctx));
ctx.out = stdout;
ctx.host = name;
+ ctx.hash_hosts = hash_hosts;
+ ctx.find_host = find_host;
+ ctx.delete_host = delete_host;
/*
* Find hosts goes to stdout, hash and deletions happen in-place
* A corner case is ssh-keygen -HF foo, which should go to stdout
*/
if (!find_host && (hash_hosts || delete_host)) {
if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
strlcat(old, ".old", sizeof(old)) >= sizeof(old))
fatal("known_hosts path too long");
umask(077);
if ((fd = mkstemp(tmp)) == -1)
fatal("mkstemp: %s", strerror(errno));
if ((ctx.out = fdopen(fd, "w")) == NULL) {
oerrno = errno;
unlink(tmp);
fatal("fdopen: %s", strerror(oerrno));
}
inplace = 1;
}
/* XXX support identity_file == "-" for stdin */
foreach_options = find_host ? HKF_WANT_MATCH : 0;
foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0;
if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ?
known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL,
foreach_options)) != 0) {
if (inplace)
unlink(tmp);
fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
}
if (inplace)
fclose(ctx.out);
if (ctx.invalid) {
error("%s is not a valid known_hosts file.", identity_file);
if (inplace) {
error("Not replacing existing known_hosts "
"file because of errors");
unlink(tmp);
}
exit(1);
} else if (delete_host && !ctx.found_key) {
logit("Host %s not found in %s", name, identity_file);
if (inplace)
unlink(tmp);
} else if (inplace) {
/* Backup existing file */
if (unlink(old) == -1 && errno != ENOENT)
fatal("unlink %.100s: %s", old, strerror(errno));
if (link(identity_file, old) == -1)
fatal("link %.100s to %.100s: %s", identity_file, old,
strerror(errno));
/* Move new one into place */
if (rename(tmp, identity_file) == -1) {
error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
strerror(errno));
unlink(tmp);
unlink(old);
exit(1);
}
printf("%s updated.\n", identity_file);
printf("Original contents retained as %s\n", old);
if (ctx.has_unhashed) {
logit("WARNING: %s contains unhashed entries", old);
logit("Delete this file to ensure privacy "
"of hostnames");
}
}
exit (find_host && !ctx.found_key);
}
/*
* Perform changing a passphrase. The argument is the passwd structure
* for the current user.
*/
static void
do_change_passphrase(struct passwd *pw)
{
char *comment;
char *old_passphrase, *passphrase1, *passphrase2;
struct stat st;
struct sshkey *private;
int r;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0)
fatal("%s: %s", identity_file, strerror(errno));
/* Try to load the file with empty passphrase. */
r = sshkey_load_private(identity_file, "", &private, &comment);
if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
if (identity_passphrase)
old_passphrase = xstrdup(identity_passphrase);
else
old_passphrase =
read_passphrase("Enter old passphrase: ",
RP_ALLOW_STDIN);
r = sshkey_load_private(identity_file, old_passphrase,
&private, &comment);
explicit_bzero(old_passphrase, strlen(old_passphrase));
free(old_passphrase);
if (r != 0)
goto badkey;
} else if (r != 0) {
badkey:
fatal("Failed to load key %s: %s", identity_file, ssh_err(r));
}
if (comment)
mprintf("Key has comment '%s'\n", comment);
/* Ask the new passphrase (twice). */
if (identity_new_passphrase) {
passphrase1 = xstrdup(identity_new_passphrase);
passphrase2 = NULL;
} else {
passphrase1 =
read_passphrase("Enter new passphrase (empty for no "
"passphrase): ", RP_ALLOW_STDIN);
passphrase2 = read_passphrase("Enter same passphrase again: ",
RP_ALLOW_STDIN);
/* Verify that they are the same. */
if (strcmp(passphrase1, passphrase2) != 0) {
explicit_bzero(passphrase1, strlen(passphrase1));
explicit_bzero(passphrase2, strlen(passphrase2));
free(passphrase1);
free(passphrase2);
printf("Pass phrases do not match. Try again.\n");
exit(1);
}
/* Destroy the other copy. */
explicit_bzero(passphrase2, strlen(passphrase2));
free(passphrase2);
}
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
comment, use_new_format, new_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s.",
identity_file, ssh_err(r));
explicit_bzero(passphrase1, strlen(passphrase1));
free(passphrase1);
sshkey_free(private);
free(comment);
exit(1);
}
/* Destroy the passphrase and the copy of the key in memory. */
explicit_bzero(passphrase1, strlen(passphrase1));
free(passphrase1);
sshkey_free(private); /* Destroys contents */
free(comment);
printf("Your identification has been saved with the new passphrase.\n");
exit(0);
}
/*
* Print the SSHFP RR.
*/
static int
-do_print_resource_record(struct passwd *pw, char *fname, char *hname)
+do_print_resource_record(struct passwd *pw, char *fname, char *hname,
+ int print_generic)
{
struct sshkey *public;
char *comment = NULL;
struct stat st;
int r;
if (fname == NULL)
fatal("%s: no filename", __func__);
if (stat(fname, &st) < 0) {
if (errno == ENOENT)
return 0;
fatal("%s: %s", fname, strerror(errno));
}
if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
fatal("Failed to read v2 public key from \"%s\": %s.",
fname, ssh_err(r));
export_dns_rr(hname, public, stdout, print_generic);
sshkey_free(public);
free(comment);
return 1;
}
/*
* Change the comment of a private key file.
*/
static void
-do_change_comment(struct passwd *pw)
+do_change_comment(struct passwd *pw, const char *identity_comment)
{
char new_comment[1024], *comment, *passphrase;
struct sshkey *private;
struct sshkey *public;
struct stat st;
FILE *f;
int r, fd;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (stat(identity_file, &st) < 0)
fatal("%s: %s", identity_file, strerror(errno));
if ((r = sshkey_load_private(identity_file, "",
&private, &comment)) == 0)
passphrase = xstrdup("");
else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
fatal("Cannot load private key \"%s\": %s.",
identity_file, ssh_err(r));
else {
if (identity_passphrase)
passphrase = xstrdup(identity_passphrase);
else if (identity_new_passphrase)
passphrase = xstrdup(identity_new_passphrase);
else
passphrase = read_passphrase("Enter passphrase: ",
RP_ALLOW_STDIN);
/* Try to load using the passphrase. */
if ((r = sshkey_load_private(identity_file, passphrase,
&private, &comment)) != 0) {
explicit_bzero(passphrase, strlen(passphrase));
free(passphrase);
fatal("Cannot load private key \"%s\": %s.",
identity_file, ssh_err(r));
}
}
if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
!use_new_format) {
error("Comments are only supported for keys stored in "
"the new format (-o).");
explicit_bzero(passphrase, strlen(passphrase));
sshkey_free(private);
exit(1);
}
if (comment)
printf("Key now has comment '%s'\n", comment);
else
printf("Key now has no comment\n");
if (identity_comment) {
strlcpy(new_comment, identity_comment, sizeof(new_comment));
} else {
printf("Enter new comment: ");
fflush(stdout);
if (!fgets(new_comment, sizeof(new_comment), stdin)) {
explicit_bzero(passphrase, strlen(passphrase));
sshkey_free(private);
exit(1);
}
new_comment[strcspn(new_comment, "\n")] = '\0';
}
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
new_comment, use_new_format, new_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
explicit_bzero(passphrase, strlen(passphrase));
free(passphrase);
sshkey_free(private);
free(comment);
exit(1);
}
explicit_bzero(passphrase, strlen(passphrase));
free(passphrase);
if ((r = sshkey_from_private(private, &public)) != 0)
fatal("sshkey_from_private failed: %s", ssh_err(r));
sshkey_free(private);
strlcat(identity_file, ".pub", sizeof(identity_file));
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
fatal("Could not save your public key in %s", identity_file);
f = fdopen(fd, "w");
if (f == NULL)
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
if ((r = sshkey_write(public, f)) != 0)
fatal("write key failed: %s", ssh_err(r));
sshkey_free(public);
fprintf(f, " %s\n", new_comment);
fclose(f);
free(comment);
printf("The comment in your key file has been changed.\n");
exit(0);
}
static void
add_flag_option(struct sshbuf *c, const char *name)
{
int r;
debug3("%s: %s", __func__, name);
if ((r = sshbuf_put_cstring(c, name)) != 0 ||
(r = sshbuf_put_string(c, NULL, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
static void
add_string_option(struct sshbuf *c, const char *name, const char *value)
{
struct sshbuf *b;
int r;
debug3("%s: %s=%s", __func__, name, value);
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_cstring(b, value)) != 0 ||
(r = sshbuf_put_cstring(c, name)) != 0 ||
(r = sshbuf_put_stringb(c, b)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
sshbuf_free(b);
}
#define OPTIONS_CRITICAL 1
#define OPTIONS_EXTENSIONS 2
static void
prepare_options_buf(struct sshbuf *c, int which)
{
size_t i;
sshbuf_reset(c);
if ((which & OPTIONS_CRITICAL) != 0 &&
certflags_command != NULL)
add_string_option(c, "force-command", certflags_command);
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_X_FWD) != 0)
add_flag_option(c, "permit-X11-forwarding");
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_AGENT_FWD) != 0)
add_flag_option(c, "permit-agent-forwarding");
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_PORT_FWD) != 0)
add_flag_option(c, "permit-port-forwarding");
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_PTY) != 0)
add_flag_option(c, "permit-pty");
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_USER_RC) != 0)
add_flag_option(c, "permit-user-rc");
if ((which & OPTIONS_CRITICAL) != 0 &&
certflags_src_addr != NULL)
add_string_option(c, "source-address", certflags_src_addr);
for (i = 0; i < ncert_userext; i++) {
if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) ||
(!cert_userext[i].crit && (which & OPTIONS_CRITICAL)))
continue;
if (cert_userext[i].val == NULL)
add_flag_option(c, cert_userext[i].key);
else {
add_string_option(c, cert_userext[i].key,
cert_userext[i].val);
}
}
}
static struct sshkey *
load_pkcs11_key(char *path)
{
#ifdef ENABLE_PKCS11
struct sshkey **keys = NULL, *public, *private = NULL;
int r, i, nkeys;
if ((r = sshkey_load_public(path, &public, NULL)) != 0)
fatal("Couldn't load CA public key \"%s\": %s",
path, ssh_err(r));
nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys);
debug3("%s: %d keys", __func__, nkeys);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
for (i = 0; i < nkeys; i++) {
if (sshkey_equal_public(public, keys[i])) {
private = keys[i];
continue;
}
sshkey_free(keys[i]);
}
free(keys);
sshkey_free(public);
return private;
#else
fatal("no pkcs11 support");
#endif /* ENABLE_PKCS11 */
}
/* Signer for sshkey_certify_custom that uses the agent */
static int
agent_signer(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen,
const char *alg, u_int compat, void *ctx)
{
int *agent_fdp = (int *)ctx;
return ssh_agent_sign(*agent_fdp, key, sigp, lenp,
data, datalen, alg, compat);
}
static void
-do_ca_sign(struct passwd *pw, int argc, char **argv)
+do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
+ unsigned long long cert_serial, int cert_serial_autoinc,
+ int argc, char **argv)
{
int r, i, fd, found, agent_fd = -1;
u_int n;
struct sshkey *ca, *public;
char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
FILE *f;
struct ssh_identitylist *agent_ids;
size_t j;
#ifdef ENABLE_PKCS11
pkcs11_init(1);
#endif
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
if (pkcs11provider != NULL) {
/* If a PKCS#11 token was specified then try to use it */
if ((ca = load_pkcs11_key(tmp)) == NULL)
fatal("No PKCS#11 key matching %s found", ca_key_path);
} else if (prefer_agent) {
/*
* Agent signature requested. Try to use agent after making
* sure the public key specified is actually present in the
* agent.
*/
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
fatal("Cannot load CA public key %s: %s",
tmp, ssh_err(r));
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
fatal("Cannot use public key for CA signature: %s",
ssh_err(r));
if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
fatal("Retrieve agent key list: %s", ssh_err(r));
found = 0;
for (j = 0; j < agent_ids->nkeys; j++) {
if (sshkey_equal(ca, agent_ids->keys[j])) {
found = 1;
break;
}
}
if (!found)
fatal("CA key %s not found in agent", tmp);
ssh_free_identitylist(agent_ids);
ca->flags |= SSHKEY_FLAG_EXT;
} else {
/* CA key is assumed to be a private key on the filesystem */
ca = load_identity(tmp);
}
free(tmp);
if (key_type_name != NULL &&
sshkey_type_from_name(key_type_name) != ca->type) {
fatal("CA key type %s doesn't match specified %s",
sshkey_ssh_name(ca), key_type_name);
}
for (i = 0; i < argc; i++) {
/* Split list of principals */
n = 0;
if (cert_principals != NULL) {
otmp = tmp = xstrdup(cert_principals);
plist = NULL;
for (; (cp = strsep(&tmp, ",")) != NULL; n++) {
plist = xreallocarray(plist, n + 1, sizeof(*plist));
if (*(plist[n] = xstrdup(cp)) == '\0')
fatal("Empty principal name");
}
free(otmp);
}
if (n > SSHKEY_CERT_MAX_PRINCIPALS)
fatal("Too many certificate principals specified");
tmp = tilde_expand_filename(argv[i], pw->pw_uid);
if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
fatal("%s: unable to open \"%s\": %s",
__func__, tmp, ssh_err(r));
if (public->type != KEY_RSA && public->type != KEY_DSA &&
public->type != KEY_ECDSA && public->type != KEY_ED25519 &&
public->type != KEY_XMSS)
fatal("%s: key \"%s\" type %s cannot be certified",
__func__, tmp, sshkey_type(public));
/* Prepare certificate to sign */
if ((r = sshkey_to_certified(public)) != 0)
fatal("Could not upgrade key %s to certificate: %s",
tmp, ssh_err(r));
public->cert->type = cert_key_type;
public->cert->serial = (u_int64_t)cert_serial;
public->cert->key_id = xstrdup(cert_key_id);
public->cert->nprincipals = n;
public->cert->principals = plist;
public->cert->valid_after = cert_valid_from;
public->cert->valid_before = cert_valid_to;
prepare_options_buf(public->cert->critical, OPTIONS_CRITICAL);
prepare_options_buf(public->cert->extensions,
OPTIONS_EXTENSIONS);
if ((r = sshkey_from_private(ca,
&public->cert->signature_key)) != 0)
fatal("sshkey_from_private (ca key): %s", ssh_err(r));
if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
if ((r = sshkey_certify_custom(public, ca,
key_type_name, agent_signer, &agent_fd)) != 0)
fatal("Couldn't certify key %s via agent: %s",
tmp, ssh_err(r));
} else {
if ((sshkey_certify(public, ca, key_type_name)) != 0)
fatal("Couldn't certify key %s: %s",
tmp, ssh_err(r));
}
if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
*cp = '\0';
xasprintf(&out, "%s-cert.pub", tmp);
free(tmp);
if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
fatal("Could not open \"%s\" for writing: %s", out,
strerror(errno));
if ((f = fdopen(fd, "w")) == NULL)
fatal("%s: fdopen: %s", __func__, strerror(errno));
if ((r = sshkey_write(public, f)) != 0)
fatal("Could not write certified key to %s: %s",
out, ssh_err(r));
fprintf(f, " %s\n", comment);
fclose(f);
if (!quiet) {
sshkey_format_cert_validity(public->cert,
valid, sizeof(valid));
logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
"valid %s", sshkey_cert_type(public),
out, public->cert->key_id,
(unsigned long long)public->cert->serial,
cert_principals != NULL ? " for " : "",
cert_principals != NULL ? cert_principals : "",
valid);
}
sshkey_free(public);
free(out);
+ if (cert_serial_autoinc)
+ cert_serial++;
}
#ifdef ENABLE_PKCS11
pkcs11_terminate();
#endif
exit(0);
}
static u_int64_t
parse_relative_time(const char *s, time_t now)
{
int64_t mul, secs;
mul = *s == '-' ? -1 : 1;
if ((secs = convtime(s + 1)) == -1)
fatal("Invalid relative certificate time %s", s);
if (mul == -1 && secs > now)
fatal("Certificate time %s cannot be represented", s);
return now + (u_int64_t)(secs * mul);
}
static void
parse_cert_times(char *timespec)
{
char *from, *to;
time_t now = time(NULL);
int64_t secs;
/* +timespec relative to now */
if (*timespec == '+' && strchr(timespec, ':') == NULL) {
if ((secs = convtime(timespec + 1)) == -1)
fatal("Invalid relative certificate life %s", timespec);
cert_valid_to = now + secs;
/*
* Backdate certificate one minute to avoid problems on hosts
* with poorly-synchronised clocks.
*/
cert_valid_from = ((now - 59)/ 60) * 60;
return;
}
/*
* from:to, where
* from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always"
* to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever"
*/
from = xstrdup(timespec);
to = strchr(from, ':');
if (to == NULL || from == to || *(to + 1) == '\0')
fatal("Invalid certificate life specification %s", timespec);
*to++ = '\0';
if (*from == '-' || *from == '+')
cert_valid_from = parse_relative_time(from, now);
else if (strcmp(from, "always") == 0)
cert_valid_from = 0;
else if (parse_absolute_time(from, &cert_valid_from) != 0)
fatal("Invalid from time \"%s\"", from);
if (*to == '-' || *to == '+')
cert_valid_to = parse_relative_time(to, now);
else if (strcmp(to, "forever") == 0)
cert_valid_to = ~(u_int64_t)0;
else if (parse_absolute_time(to, &cert_valid_to) != 0)
fatal("Invalid to time \"%s\"", to);
if (cert_valid_to <= cert_valid_from)
fatal("Empty certificate validity interval");
free(from);
}
static void
add_cert_option(char *opt)
{
char *val, *cp;
int iscrit = 0;
if (strcasecmp(opt, "clear") == 0)
certflags_flags = 0;
else if (strcasecmp(opt, "no-x11-forwarding") == 0)
certflags_flags &= ~CERTOPT_X_FWD;
else if (strcasecmp(opt, "permit-x11-forwarding") == 0)
certflags_flags |= CERTOPT_X_FWD;
else if (strcasecmp(opt, "no-agent-forwarding") == 0)
certflags_flags &= ~CERTOPT_AGENT_FWD;
else if (strcasecmp(opt, "permit-agent-forwarding") == 0)
certflags_flags |= CERTOPT_AGENT_FWD;
else if (strcasecmp(opt, "no-port-forwarding") == 0)
certflags_flags &= ~CERTOPT_PORT_FWD;
else if (strcasecmp(opt, "permit-port-forwarding") == 0)
certflags_flags |= CERTOPT_PORT_FWD;
else if (strcasecmp(opt, "no-pty") == 0)
certflags_flags &= ~CERTOPT_PTY;
else if (strcasecmp(opt, "permit-pty") == 0)
certflags_flags |= CERTOPT_PTY;
else if (strcasecmp(opt, "no-user-rc") == 0)
certflags_flags &= ~CERTOPT_USER_RC;
else if (strcasecmp(opt, "permit-user-rc") == 0)
certflags_flags |= CERTOPT_USER_RC;
else if (strncasecmp(opt, "force-command=", 14) == 0) {
val = opt + 14;
if (*val == '\0')
fatal("Empty force-command option");
if (certflags_command != NULL)
fatal("force-command already specified");
certflags_command = xstrdup(val);
} else if (strncasecmp(opt, "source-address=", 15) == 0) {
val = opt + 15;
if (*val == '\0')
fatal("Empty source-address option");
if (certflags_src_addr != NULL)
fatal("source-address already specified");
if (addr_match_cidr_list(NULL, val) != 0)
fatal("Invalid source-address list");
certflags_src_addr = xstrdup(val);
} else if (strncasecmp(opt, "extension:", 10) == 0 ||
(iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
val = xstrdup(strchr(opt, ':') + 1);
if ((cp = strchr(val, '=')) != NULL)
*cp++ = '\0';
cert_userext = xreallocarray(cert_userext, ncert_userext + 1,
sizeof(*cert_userext));
cert_userext[ncert_userext].key = val;
cert_userext[ncert_userext].val = cp == NULL ?
NULL : xstrdup(cp);
cert_userext[ncert_userext].crit = iscrit;
ncert_userext++;
} else
fatal("Unsupported certificate option \"%s\"", opt);
}
static void
show_options(struct sshbuf *optbuf, int in_critical)
{
char *name, *arg;
struct sshbuf *options, *option = NULL;
int r;
if ((options = sshbuf_fromb(optbuf)) == NULL)
fatal("%s: sshbuf_fromb failed", __func__);
while (sshbuf_len(options) != 0) {
sshbuf_free(option);
option = NULL;
if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 ||
(r = sshbuf_froms(options, &option)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
printf(" %s", name);
if (!in_critical &&
(strcmp(name, "permit-X11-forwarding") == 0 ||
strcmp(name, "permit-agent-forwarding") == 0 ||
strcmp(name, "permit-port-forwarding") == 0 ||
strcmp(name, "permit-pty") == 0 ||
strcmp(name, "permit-user-rc") == 0))
printf("\n");
else if (in_critical &&
(strcmp(name, "force-command") == 0 ||
strcmp(name, "source-address") == 0)) {
if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
printf(" %s\n", arg);
free(arg);
} else {
printf(" UNKNOWN OPTION (len %zu)\n",
sshbuf_len(option));
sshbuf_reset(option);
}
free(name);
if (sshbuf_len(option) != 0)
fatal("Option corrupt: extra data at end");
}
sshbuf_free(option);
sshbuf_free(options);
}
static void
print_cert(struct sshkey *key)
{
char valid[64], *key_fp, *ca_fp;
u_int i;
key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
ca_fp = sshkey_fingerprint(key->cert->signature_key,
fingerprint_hash, SSH_FP_DEFAULT);
if (key_fp == NULL || ca_fp == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
sshkey_cert_type(key));
printf(" Public key: %s %s\n", sshkey_type(key), key_fp);
- printf(" Signing CA: %s %s\n",
- sshkey_type(key->cert->signature_key), ca_fp);
+ printf(" Signing CA: %s %s (using %s)\n",
+ sshkey_type(key->cert->signature_key), ca_fp,
+ key->cert->signature_type);
printf(" Key ID: \"%s\"\n", key->cert->key_id);
printf(" Serial: %llu\n", (unsigned long long)key->cert->serial);
printf(" Valid: %s\n", valid);
printf(" Principals: ");
if (key->cert->nprincipals == 0)
printf("(none)\n");
else {
for (i = 0; i < key->cert->nprincipals; i++)
printf("\n %s",
key->cert->principals[i]);
printf("\n");
}
printf(" Critical Options: ");
if (sshbuf_len(key->cert->critical) == 0)
printf("(none)\n");
else {
printf("\n");
show_options(key->cert->critical, 1);
}
printf(" Extensions: ");
if (sshbuf_len(key->cert->extensions) == 0)
printf("(none)\n");
else {
printf("\n");
show_options(key->cert->extensions, 0);
}
}
static void
do_show_cert(struct passwd *pw)
{
struct sshkey *key = NULL;
struct stat st;
int r, is_stdin = 0, ok = 0;
FILE *f;
char *cp, *line = NULL;
const char *path;
size_t linesize = 0;
u_long lnum = 0;
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
if (strcmp(identity_file, "-") != 0 && stat(identity_file, &st) < 0)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
path = identity_file;
if (strcmp(path, "-") == 0) {
f = stdin;
path = "(stdin)";
is_stdin = 1;
} else if ((f = fopen(identity_file, "r")) == NULL)
fatal("fopen %s: %s", identity_file, strerror(errno));
while (getline(&line, &linesize, f) != -1) {
lnum++;
sshkey_free(key);
key = NULL;
/* Trim leading space and comments */
cp = line + strspn(line, " \t");
if (*cp == '#' || *cp == '\0')
continue;
if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new");
if ((r = sshkey_read(key, &cp)) != 0) {
error("%s:%lu: invalid key: %s", path,
lnum, ssh_err(r));
continue;
}
if (!sshkey_is_cert(key)) {
error("%s:%lu is not a certificate", path, lnum);
continue;
}
ok = 1;
if (!is_stdin && lnum == 1)
printf("%s:\n", path);
else
printf("%s:%lu:\n", path, lnum);
print_cert(key);
}
free(line);
sshkey_free(key);
fclose(f);
exit(ok ? 0 : 1);
}
static void
load_krl(const char *path, struct ssh_krl **krlp)
{
struct sshbuf *krlbuf;
int r, fd;
if ((krlbuf = sshbuf_new()) == NULL)
fatal("sshbuf_new failed");
if ((fd = open(path, O_RDONLY)) == -1)
fatal("open %s: %s", path, strerror(errno));
if ((r = sshkey_load_file(fd, krlbuf)) != 0)
fatal("Unable to load KRL: %s", ssh_err(r));
close(fd);
/* XXX check sigs */
if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 ||
*krlp == NULL)
fatal("Invalid KRL file: %s", ssh_err(r));
sshbuf_free(krlbuf);
}
static void
hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
const char *file, u_long lnum)
{
char *tmp;
size_t tlen;
struct sshbuf *b;
int r;
if (strncmp(cp, "SHA256:", 7) != 0)
fatal("%s:%lu: unsupported hash algorithm", file, lnum);
cp += 7;
/*
* OpenSSH base64 hashes omit trailing '='
* characters; put them back for decode.
*/
tlen = strlen(cp);
tmp = xmalloc(tlen + 4 + 1);
strlcpy(tmp, cp, tlen + 1);
while ((tlen % 4) != 0) {
tmp[tlen++] = '=';
tmp[tlen] = '\0';
}
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_b64tod(b, tmp)) != 0)
fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r));
free(tmp);
*lenp = sshbuf_len(b);
*blobp = xmalloc(*lenp);
memcpy(*blobp, sshbuf_ptr(b), *lenp);
sshbuf_free(b);
}
static void
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
const struct sshkey *ca, struct ssh_krl *krl)
{
struct sshkey *key = NULL;
u_long lnum = 0;
char *path, *cp, *ep, *line = NULL;
u_char *blob = NULL;
size_t blen = 0, linesize = 0;
unsigned long long serial, serial2;
int i, was_explicit_key, was_sha1, was_sha256, was_hash, r;
FILE *krl_spec;
path = tilde_expand_filename(file, pw->pw_uid);
if (strcmp(path, "-") == 0) {
krl_spec = stdin;
free(path);
path = xstrdup("(standard input)");
} else if ((krl_spec = fopen(path, "r")) == NULL)
fatal("fopen %s: %s", path, strerror(errno));
if (!quiet)
printf("Revoking from %s\n", path);
while (getline(&line, &linesize, krl_spec) != -1) {
lnum++;
was_explicit_key = was_sha1 = was_sha256 = was_hash = 0;
cp = line + strspn(line, " \t");
/* Trim trailing space, comments and strip \n */
for (i = 0, r = -1; cp[i] != '\0'; i++) {
if (cp[i] == '#' || cp[i] == '\n') {
cp[i] = '\0';
break;
}
if (cp[i] == ' ' || cp[i] == '\t') {
/* Remember the start of a span of whitespace */
if (r == -1)
r = i;
} else
r = -1;
}
if (r != -1)
cp[r] = '\0';
if (*cp == '\0')
continue;
if (strncasecmp(cp, "serial:", 7) == 0) {
if (ca == NULL && !wild_ca) {
fatal("revoking certificates by serial number "
"requires specification of a CA key");
}
cp += 7;
cp = cp + strspn(cp, " \t");
errno = 0;
serial = strtoull(cp, &ep, 0);
if (*cp == '\0' || (*ep != '\0' && *ep != '-'))
fatal("%s:%lu: invalid serial \"%s\"",
path, lnum, cp);
if (errno == ERANGE && serial == ULLONG_MAX)
fatal("%s:%lu: serial out of range",
path, lnum);
serial2 = serial;
if (*ep == '-') {
cp = ep + 1;
errno = 0;
serial2 = strtoull(cp, &ep, 0);
if (*cp == '\0' || *ep != '\0')
fatal("%s:%lu: invalid serial \"%s\"",
path, lnum, cp);
if (errno == ERANGE && serial2 == ULLONG_MAX)
fatal("%s:%lu: serial out of range",
path, lnum);
if (serial2 <= serial)
fatal("%s:%lu: invalid serial range "
"%llu:%llu", path, lnum,
(unsigned long long)serial,
(unsigned long long)serial2);
}
if (ssh_krl_revoke_cert_by_serial_range(krl,
ca, serial, serial2) != 0) {
fatal("%s: revoke serial failed",
__func__);
}
} else if (strncasecmp(cp, "id:", 3) == 0) {
if (ca == NULL && !wild_ca) {
fatal("revoking certificates by key ID "
"requires specification of a CA key");
}
cp += 3;
cp = cp + strspn(cp, " \t");
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
fatal("%s: revoke key ID failed", __func__);
} else if (strncasecmp(cp, "hash:", 5) == 0) {
cp += 5;
cp = cp + strspn(cp, " \t");
hash_to_blob(cp, &blob, &blen, file, lnum);
r = ssh_krl_revoke_key_sha256(krl, blob, blen);
} else {
if (strncasecmp(cp, "key:", 4) == 0) {
cp += 4;
cp = cp + strspn(cp, " \t");
was_explicit_key = 1;
} else if (strncasecmp(cp, "sha1:", 5) == 0) {
cp += 5;
cp = cp + strspn(cp, " \t");
was_sha1 = 1;
} else if (strncasecmp(cp, "sha256:", 7) == 0) {
cp += 7;
cp = cp + strspn(cp, " \t");
was_sha256 = 1;
/*
* Just try to process the line as a key.
* Parsing will fail if it isn't.
*/
}
if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new");
if ((r = sshkey_read(key, &cp)) != 0)
fatal("%s:%lu: invalid key: %s",
path, lnum, ssh_err(r));
if (was_explicit_key)
r = ssh_krl_revoke_key_explicit(krl, key);
else if (was_sha1) {
if (sshkey_fingerprint_raw(key,
SSH_DIGEST_SHA1, &blob, &blen) != 0) {
fatal("%s:%lu: fingerprint failed",
file, lnum);
}
r = ssh_krl_revoke_key_sha1(krl, blob, blen);
} else if (was_sha256) {
if (sshkey_fingerprint_raw(key,
SSH_DIGEST_SHA256, &blob, &blen) != 0) {
fatal("%s:%lu: fingerprint failed",
file, lnum);
}
r = ssh_krl_revoke_key_sha256(krl, blob, blen);
} else
r = ssh_krl_revoke_key(krl, key);
if (r != 0)
fatal("%s: revoke key failed: %s",
__func__, ssh_err(r));
freezero(blob, blen);
blob = NULL;
blen = 0;
sshkey_free(key);
}
}
if (strcmp(path, "-") != 0)
fclose(krl_spec);
free(line);
free(path);
}
static void
-do_gen_krl(struct passwd *pw, int updating, int argc, char **argv)
+do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
+ unsigned long long krl_version, const char *krl_comment,
+ int argc, char **argv)
{
struct ssh_krl *krl;
struct stat sb;
struct sshkey *ca = NULL;
int fd, i, r, wild_ca = 0;
char *tmp;
struct sshbuf *kbuf;
if (*identity_file == '\0')
fatal("KRL generation requires an output file");
if (stat(identity_file, &sb) == -1) {
if (errno != ENOENT)
fatal("Cannot access KRL \"%s\": %s",
identity_file, strerror(errno));
if (updating)
fatal("KRL \"%s\" does not exist", identity_file);
}
if (ca_key_path != NULL) {
if (strcasecmp(ca_key_path, "none") == 0)
wild_ca = 1;
else {
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
fatal("Cannot load CA public key %s: %s",
tmp, ssh_err(r));
free(tmp);
}
}
if (updating)
load_krl(identity_file, &krl);
else if ((krl = ssh_krl_init()) == NULL)
fatal("couldn't create KRL");
- if (cert_serial != 0)
- ssh_krl_set_version(krl, cert_serial);
- if (identity_comment != NULL)
- ssh_krl_set_comment(krl, identity_comment);
+ if (krl_version != 0)
+ ssh_krl_set_version(krl, krl_version);
+ if (krl_comment != NULL)
+ ssh_krl_set_comment(krl, krl_comment);
for (i = 0; i < argc; i++)
update_krl_from_file(pw, argv[i], wild_ca, ca, krl);
if ((kbuf = sshbuf_new()) == NULL)
fatal("sshbuf_new failed");
if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0)
fatal("Couldn't generate KRL");
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
fatal("open %s: %s", identity_file, strerror(errno));
if (atomicio(vwrite, fd, sshbuf_mutable_ptr(kbuf), sshbuf_len(kbuf)) !=
sshbuf_len(kbuf))
fatal("write %s: %s", identity_file, strerror(errno));
close(fd);
sshbuf_free(kbuf);
ssh_krl_free(krl);
sshkey_free(ca);
}
static void
do_check_krl(struct passwd *pw, int argc, char **argv)
{
int i, r, ret = 0;
char *comment;
struct ssh_krl *krl;
struct sshkey *k;
if (*identity_file == '\0')
fatal("KRL checking requires an input file");
load_krl(identity_file, &krl);
for (i = 0; i < argc; i++) {
if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
fatal("Cannot load public key %s: %s",
argv[i], ssh_err(r));
r = ssh_krl_check_key(krl, k);
printf("%s%s%s%s: %s\n", argv[i],
*comment ? " (" : "", comment, *comment ? ")" : "",
r == 0 ? "ok" : "REVOKED");
if (r != 0)
ret = 1;
sshkey_free(k);
free(comment);
}
ssh_krl_free(krl);
exit(ret);
}
static void
usage(void)
{
fprintf(stderr,
- "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa]\n"
+ "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa] [-m format]\n"
" [-N new_passphrase] [-C comment] [-f output_keyfile]\n"
- " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n"
+ " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-m format]\n"
+ " [-f keyfile]\n"
" ssh-keygen -i [-m key_format] [-f input_keyfile]\n"
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
" ssh-keygen -y [-f input_keyfile]\n"
" ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
" ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
" ssh-keygen -B [-f input_keyfile]\n");
#ifdef ENABLE_PKCS11
fprintf(stderr,
" ssh-keygen -D pkcs11\n");
#endif
fprintf(stderr,
" ssh-keygen -F hostname [-f known_hosts_file] [-l]\n"
" ssh-keygen -H [-f known_hosts_file]\n"
" ssh-keygen -R hostname [-f known_hosts_file]\n"
" ssh-keygen -r hostname [-f input_keyfile] [-g]\n"
#ifdef WITH_OPENSSL
" ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n"
" ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
" [-j start_line] [-K checkpt] [-W generator]\n"
#endif
" ssh-keygen -s ca_key -I certificate_identity [-h] [-U]\n"
" [-D pkcs11_provider] [-n principals] [-O option]\n"
" [-V validity_interval] [-z serial_number] file ...\n"
" ssh-keygen -L [-f input_keyfile]\n"
" ssh-keygen -A\n"
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
" file ...\n"
" ssh-keygen -Q -f krl_file file ...\n");
exit(1);
}
/*
* Main program for key management.
*/
int
main(int argc, char **argv)
{
char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2;
char *rr_hostname = NULL, *ep, *fp, *ra;
struct sshkey *private, *public;
struct passwd *pw;
struct stat st;
int r, opt, type, fd;
+ int change_passphrase = 0, change_comment = 0, show_cert = 0;
+ int find_host = 0, delete_host = 0, hash_hosts = 0;
int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
+ int prefer_agent = 0, convert_to = 0, convert_from = 0;
+ int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
+ unsigned long long cert_serial = 0;
+ char *identity_comment = NULL, *ca_key_path = NULL;
+ u_int bits = 0;
FILE *f;
const char *errstr;
+ int log_level = SYSLOG_LEVEL_INFO;
#ifdef WITH_OPENSSL
/* Moduli generation/screening */
char out_file[PATH_MAX], *checkpoint = NULL;
u_int32_t memory = 0, generator_wanted = 0;
int do_gen_candidates = 0, do_screen_candidates = 0;
unsigned long start_lineno = 0, lines_to_process = 0;
BIGNUM *start = NULL;
#endif
extern int optind;
extern char *optarg;
ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
__progname = ssh_get_progname(argv[0]);
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
- log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
-
seed_rng();
+ log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
+
msetlocale();
/* we need this for the home * directory. */
pw = getpwuid(getuid());
if (!pw)
fatal("No user exists for uid %lu", (u_long)getuid());
if (gethostname(hostname, sizeof(hostname)) < 0)
fatal("gethostname: %s", strerror(errno));
/* Remaining characters: Ydw */
while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy"
"C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Z:"
"a:b:f:g:j:m:n:r:s:t:z:")) != -1) {
switch (opt) {
case 'A':
gen_all_hostkeys = 1;
break;
case 'b':
bits = (u_int32_t)strtonum(optarg, 10, 32768, &errstr);
if (errstr)
fatal("Bits has bad value %s (%s)",
optarg, errstr);
break;
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
if (fingerprint_hash == -1)
fatal("Invalid hash algorithm \"%s\"", optarg);
break;
case 'F':
find_host = 1;
rr_hostname = optarg;
break;
case 'H':
hash_hosts = 1;
break;
case 'I':
cert_key_id = optarg;
break;
case 'R':
delete_host = 1;
rr_hostname = optarg;
break;
case 'L':
show_cert = 1;
break;
case 'l':
print_fingerprint = 1;
break;
case 'B':
print_bubblebabble = 1;
break;
case 'm':
if (strcasecmp(optarg, "RFC4716") == 0 ||
strcasecmp(optarg, "ssh2") == 0) {
convert_format = FMT_RFC4716;
break;
}
if (strcasecmp(optarg, "PKCS8") == 0) {
convert_format = FMT_PKCS8;
break;
}
if (strcasecmp(optarg, "PEM") == 0) {
convert_format = FMT_PEM;
use_new_format = 0;
break;
}
fatal("Unsupported conversion format \"%s\"", optarg);
case 'n':
cert_principals = optarg;
break;
case 'o':
/* no-op; new format is already the default */
break;
case 'p':
change_passphrase = 1;
break;
case 'c':
change_comment = 1;
break;
case 'f':
if (strlcpy(identity_file, optarg,
sizeof(identity_file)) >= sizeof(identity_file))
fatal("Identity filename too long");
have_identity = 1;
break;
case 'g':
print_generic = 1;
break;
case 'P':
identity_passphrase = optarg;
break;
case 'N':
identity_new_passphrase = optarg;
break;
case 'Q':
check_krl = 1;
break;
case 'O':
add_cert_option(optarg);
break;
case 'Z':
new_format_cipher = optarg;
break;
case 'C':
identity_comment = optarg;
break;
case 'q':
quiet = 1;
break;
case 'e':
case 'x':
/* export key */
convert_to = 1;
break;
case 'h':
cert_key_type = SSH2_CERT_TYPE_HOST;
certflags_flags = 0;
break;
case 'k':
gen_krl = 1;
break;
case 'i':
case 'X':
/* import key */
convert_from = 1;
break;
case 'y':
print_public = 1;
break;
case 's':
ca_key_path = optarg;
break;
case 't':
key_type_name = optarg;
break;
case 'D':
pkcs11provider = optarg;
break;
case 'U':
prefer_agent = 1;
break;
case 'u':
update_krl = 1;
break;
case 'v':
if (log_level == SYSLOG_LEVEL_INFO)
log_level = SYSLOG_LEVEL_DEBUG1;
else {
if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
log_level < SYSLOG_LEVEL_DEBUG3)
log_level++;
}
break;
case 'r':
rr_hostname = optarg;
break;
case 'a':
rounds = (int)strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr)
fatal("Invalid number: %s (%s)",
optarg, errstr);
break;
case 'V':
parse_cert_times(optarg);
break;
case 'z':
errno = 0;
+ if (*optarg == '+') {
+ cert_serial_autoinc = 1;
+ optarg++;
+ }
cert_serial = strtoull(optarg, &ep, 10);
if (*optarg < '0' || *optarg > '9' || *ep != '\0' ||
(errno == ERANGE && cert_serial == ULLONG_MAX))
fatal("Invalid serial number \"%s\"", optarg);
break;
#ifdef WITH_OPENSSL
/* Moduli generation/screening */
case 'G':
do_gen_candidates = 1;
if (strlcpy(out_file, optarg, sizeof(out_file)) >=
sizeof(out_file))
fatal("Output filename too long");
break;
case 'J':
lines_to_process = strtoul(optarg, NULL, 10);
break;
case 'j':
start_lineno = strtoul(optarg, NULL, 10);
break;
case 'K':
if (strlen(optarg) >= PATH_MAX)
fatal("Checkpoint filename too long");
checkpoint = xstrdup(optarg);
break;
case 'M':
memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX,
&errstr);
if (errstr)
fatal("Memory limit is %s: %s", errstr, optarg);
break;
case 'S':
/* XXX - also compare length against bits */
if (BN_hex2bn(&start, optarg) == 0)
fatal("Invalid start point.");
break;
case 'T':
do_screen_candidates = 1;
if (strlcpy(out_file, optarg, sizeof(out_file)) >=
sizeof(out_file))
fatal("Output filename too long");
break;
case 'W':
generator_wanted = (u_int32_t)strtonum(optarg, 1,
UINT_MAX, &errstr);
if (errstr != NULL)
fatal("Desired generator invalid: %s (%s)",
optarg, errstr);
break;
#endif /* WITH_OPENSSL */
case '?':
default:
usage();
}
}
/* reinit */
log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1);
argv += optind;
argc -= optind;
if (ca_key_path != NULL) {
if (argc < 1 && !gen_krl) {
error("Too few arguments.");
usage();
}
} else if (argc > 0 && !gen_krl && !check_krl) {
error("Too many arguments.");
usage();
}
if (change_passphrase && change_comment) {
error("Can only have one of -p and -c.");
usage();
}
if (print_fingerprint && (delete_host || hash_hosts)) {
error("Cannot use -l with -H or -R.");
usage();
}
if (gen_krl) {
- do_gen_krl(pw, update_krl, argc, argv);
+ do_gen_krl(pw, update_krl, ca_key_path,
+ cert_serial, identity_comment, argc, argv);
return (0);
}
if (check_krl) {
do_check_krl(pw, argc, argv);
return (0);
}
if (ca_key_path != NULL) {
if (cert_key_id == NULL)
fatal("Must specify key id (-I) when certifying");
- do_ca_sign(pw, argc, argv);
+ do_ca_sign(pw, ca_key_path, prefer_agent,
+ cert_serial, cert_serial_autoinc, argc, argv);
}
if (show_cert)
do_show_cert(pw);
- if (delete_host || hash_hosts || find_host)
- do_known_hosts(pw, rr_hostname);
+ if (delete_host || hash_hosts || find_host) {
+ do_known_hosts(pw, rr_hostname, find_host,
+ delete_host, hash_hosts);
+ }
if (pkcs11provider != NULL)
do_download(pw);
if (print_fingerprint || print_bubblebabble)
do_fingerprint(pw);
if (change_passphrase)
do_change_passphrase(pw);
if (change_comment)
- do_change_comment(pw);
+ do_change_comment(pw, identity_comment);
#ifdef WITH_OPENSSL
if (convert_to)
do_convert_to(pw);
if (convert_from)
do_convert_from(pw);
#endif
if (print_public)
do_print_public(pw);
if (rr_hostname != NULL) {
unsigned int n = 0;
if (have_identity) {
- n = do_print_resource_record(pw,
- identity_file, rr_hostname);
+ n = do_print_resource_record(pw, identity_file,
+ rr_hostname, print_generic);
if (n == 0)
fatal("%s: %s", identity_file, strerror(errno));
exit(0);
} else {
n += do_print_resource_record(pw,
- _PATH_HOST_RSA_KEY_FILE, rr_hostname);
+ _PATH_HOST_RSA_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_DSA_KEY_FILE, rr_hostname);
+ _PATH_HOST_DSA_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
+ _PATH_HOST_ECDSA_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_ED25519_KEY_FILE, rr_hostname);
+ _PATH_HOST_ED25519_KEY_FILE, rr_hostname,
+ print_generic);
n += do_print_resource_record(pw,
- _PATH_HOST_XMSS_KEY_FILE, rr_hostname);
+ _PATH_HOST_XMSS_KEY_FILE, rr_hostname,
+ print_generic);
if (n == 0)
fatal("no keys found.");
exit(0);
}
}
#ifdef WITH_OPENSSL
if (do_gen_candidates) {
FILE *out = fopen(out_file, "w");
if (out == NULL) {
error("Couldn't open modulus candidate file \"%s\": %s",
out_file, strerror(errno));
return (1);
}
if (bits == 0)
bits = DEFAULT_BITS;
if (gen_candidates(out, memory, bits, start) != 0)
fatal("modulus candidate generation failed");
return (0);
}
if (do_screen_candidates) {
FILE *in;
FILE *out = fopen(out_file, "a");
if (have_identity && strcmp(identity_file, "-") != 0) {
if ((in = fopen(identity_file, "r")) == NULL) {
fatal("Couldn't open modulus candidate "
"file \"%s\": %s", identity_file,
strerror(errno));
}
} else
in = stdin;
if (out == NULL) {
fatal("Couldn't open moduli file \"%s\": %s",
out_file, strerror(errno));
}
if (prime_test(in, out, rounds == 0 ? 100 : rounds,
generator_wanted, checkpoint,
start_lineno, lines_to_process) != 0)
fatal("modulus screening failed");
return (0);
}
#endif
if (gen_all_hostkeys) {
do_gen_all_hostkeys(pw);
return (0);
}
if (key_type_name == NULL)
key_type_name = DEFAULT_KEY_TYPE_NAME;
type = sshkey_type_from_name(key_type_name);
type_bits_valid(type, key_type_name, &bits);
if (!quiet)
printf("Generating public/private %s key pair.\n",
key_type_name);
if ((r = sshkey_generate(type, bits, &private)) != 0)
fatal("sshkey_generate failed");
if ((r = sshkey_from_private(private, &public)) != 0)
fatal("sshkey_from_private failed: %s\n", ssh_err(r));
if (!have_identity)
ask_filename(pw, "Enter file in which to save the key");
/* Create ~/.ssh directory if it doesn't already exist. */
snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
pw->pw_dir, _PATH_SSH_USER_DIR);
if (strstr(identity_file, dotsshdir) != NULL) {
if (stat(dotsshdir, &st) < 0) {
if (errno != ENOENT) {
error("Could not stat %s: %s", dotsshdir,
strerror(errno));
} else if (mkdir(dotsshdir, 0700) < 0) {
error("Could not create directory '%s': %s",
dotsshdir, strerror(errno));
} else if (!quiet)
printf("Created directory '%s'.\n", dotsshdir);
}
}
/* If the file already exists, ask the user to confirm. */
if (stat(identity_file, &st) >= 0) {
char yesno[3];
printf("%s already exists.\n", identity_file);
printf("Overwrite (y/n)? ");
fflush(stdout);
if (fgets(yesno, sizeof(yesno), stdin) == NULL)
exit(1);
if (yesno[0] != 'y' && yesno[0] != 'Y')
exit(1);
}
/* Ask for a passphrase (twice). */
if (identity_passphrase)
passphrase1 = xstrdup(identity_passphrase);
else if (identity_new_passphrase)
passphrase1 = xstrdup(identity_new_passphrase);
else {
passphrase_again:
passphrase1 =
read_passphrase("Enter passphrase (empty for no "
"passphrase): ", RP_ALLOW_STDIN);
passphrase2 = read_passphrase("Enter same passphrase again: ",
RP_ALLOW_STDIN);
if (strcmp(passphrase1, passphrase2) != 0) {
/*
* The passphrases do not match. Clear them and
* retry.
*/
explicit_bzero(passphrase1, strlen(passphrase1));
explicit_bzero(passphrase2, strlen(passphrase2));
free(passphrase1);
free(passphrase2);
printf("Passphrases do not match. Try again.\n");
goto passphrase_again;
}
/* Clear the other copy of the passphrase. */
explicit_bzero(passphrase2, strlen(passphrase2));
free(passphrase2);
}
if (identity_comment) {
strlcpy(comment, identity_comment, sizeof(comment));
} else {
/* Create default comment field for the passphrase. */
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname);
}
/* Save the key with the given passphrase and comment. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
comment, use_new_format, new_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
explicit_bzero(passphrase1, strlen(passphrase1));
free(passphrase1);
exit(1);
}
/* Clear the passphrase. */
explicit_bzero(passphrase1, strlen(passphrase1));
free(passphrase1);
/* Clear the private key and the random number generator. */
sshkey_free(private);
if (!quiet)
printf("Your identification has been saved in %s.\n", identity_file);
strlcat(identity_file, ".pub", sizeof(identity_file));
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
fatal("Unable to save public key to %s: %s",
identity_file, strerror(errno));
if ((f = fdopen(fd, "w")) == NULL)
fatal("fdopen %s failed: %s", identity_file, strerror(errno));
if ((r = sshkey_write(public, f)) != 0)
error("write key failed: %s", ssh_err(r));
fprintf(f, " %s\n", comment);
if (ferror(f) || fclose(f) != 0)
fatal("write public failed: %s", strerror(errno));
if (!quiet) {
fp = sshkey_fingerprint(public, fingerprint_hash,
SSH_FP_DEFAULT);
ra = sshkey_fingerprint(public, fingerprint_hash,
SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("sshkey_fingerprint failed");
printf("Your public key has been saved in %s.\n",
identity_file);
printf("The key fingerprint is:\n");
printf("%s %s\n", fp, comment);
printf("The key's randomart image is:\n");
printf("%s\n", ra);
free(ra);
free(fp);
}
sshkey_free(public);
exit(0);
}
diff --git a/ssh-keyscan.0 b/ssh-keyscan.0
index 497ac0d9ee74..d372f7c7a3ef 100644
--- a/ssh-keyscan.0
+++ b/ssh-keyscan.0
@@ -1,96 +1,96 @@
SSH-KEYSCAN(1) General Commands Manual SSH-KEYSCAN(1)
NAME
ssh-keyscan M-bM-^@M-^S gather SSH public keys
SYNOPSIS
ssh-keyscan [-46cDHv] [-f file] [-p port] [-T timeout] [-t type]
[host | addrlist namelist]
DESCRIPTION
ssh-keyscan is a utility for gathering the public SSH host keys of a
number of hosts. It was designed to aid in building and verifying
ssh_known_hosts files, the format of which is documented in sshd(8).
ssh-keyscan provides a minimal interface suitable for use by shell and
perl scripts.
ssh-keyscan uses non-blocking socket I/O to contact as many hosts as
possible in parallel, so it is very efficient. The keys from a domain of
1,000 hosts can be collected in tens of seconds, even when some of those
hosts are down or do not run sshd(8). For scanning, one does not need
login access to the machines that are being scanned, nor does the
scanning process involve any encryption.
The options are as follows:
-4 Force ssh-keyscan to use IPv4 addresses only.
-6 Force ssh-keyscan to use IPv6 addresses only.
-c Request certificates from target hosts instead of plain keys.
-D Print keys found as SSHFP DNS records. The default is to print
keys in a format usable as a ssh(1) known_hosts file.
-f file
Read hosts or M-bM-^@M-^\addrlist namelistM-bM-^@M-^] pairs from file, one per line.
If M-bM-^@M-^X-M-bM-^@M-^Y is supplied instead of a filename, ssh-keyscan will read
from the standard input. Input is expected in the format:
1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
-H Hash all hostnames and addresses in the output. Hashed names may
be used normally by ssh(1) and sshd(8), but they do not reveal
identifying information should the file's contents be disclosed.
-p port
Connect to port on the remote host.
-T timeout
Set the timeout for connection attempts. If timeout seconds have
elapsed since a connection was initiated to a host or since the
last time anything was read from that host, the connection is
closed and the host in question considered unavailable. The
default is 5 seconds.
-t type
Specify the type of the key to fetch from the scanned hosts. The
possible values are M-bM-^@M-^\dsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], M-bM-^@M-^\ed25519M-bM-^@M-^], or M-bM-^@M-^\rsaM-bM-^@M-^].
Multiple values may be specified by separating them with commas.
The default is to fetch M-bM-^@M-^\rsaM-bM-^@M-^], M-bM-^@M-^\ecdsaM-bM-^@M-^], and M-bM-^@M-^\ed25519M-bM-^@M-^] keys.
-v Verbose mode: print debugging messages about progress.
If an ssh_known_hosts file is constructed using ssh-keyscan without
verifying the keys, users will be vulnerable to man in the middle
attacks. On the other hand, if the security model allows such a risk,
ssh-keyscan can help in the detection of tampered keyfiles or man in the
middle attacks which have begun after the ssh_known_hosts file was
created.
FILES
/etc/ssh/ssh_known_hosts
EXAMPLES
Print the RSA host key for machine hostname:
$ ssh-keyscan -t rsa hostname
Find all hosts from the file ssh_hosts which have new or different keys
from those in the sorted file ssh_known_hosts:
$ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \
sort -u - ssh_known_hosts | diff ssh_known_hosts -
SEE ALSO
ssh(1), sshd(8)
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints, RFC
4255, 2006.
AUTHORS
David Mazieres <dm@lcs.mit.edu> wrote the initial version, and Wayne
Davison <wayned@users.sourceforge.net> added support for protocol version
2.
-OpenBSD 6.4 March 5, 2018 OpenBSD 6.4
+OpenBSD 6.5 March 5, 2018 OpenBSD 6.5
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 38b1c548be3e..2ed041559958 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,807 +1,810 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.120 2018/06/06 18:29:18 markus Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.126 2019/01/26 22:35:01 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
* Modification and redistribution in source and binary forms is
* permitted provided that due credit is given to the author and the
* OpenBSD project by leaving this copyright notice intact.
*/
#include "includes.h"
#include <sys/types.h>
#include "openbsd-compat/sys-queue.h"
#include <sys/resource.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/bn.h>
#include <netdb.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "xmalloc.h"
#include "ssh.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "cipher.h"
#include "kex.h"
#include "compat.h"
#include "myproposal.h"
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "atomicio.h"
#include "misc.h"
#include "hostfile.h"
#include "ssherr.h"
#include "ssh_api.h"
#include "dns.h"
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
Default value is AF_UNSPEC means both IPv4 and IPv6. */
int IPv4or6 = AF_UNSPEC;
int ssh_port = SSH_DEFAULT_PORT;
#define KT_DSA (1)
#define KT_RSA (1<<1)
#define KT_ECDSA (1<<2)
#define KT_ED25519 (1<<3)
#define KT_XMSS (1<<4)
#define KT_MIN KT_DSA
#define KT_MAX KT_XMSS
int get_cert = 0;
int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519;
int hash_hosts = 0; /* Hash hostname on output */
int print_sshfp = 0; /* Print SSHFP records instead of known_hosts */
+int found_one = 0; /* Successfully found a key */
+
#define MAXMAXFD 256
/* The number of seconds after which to give up on a TCP connection */
int timeout = 5;
int maxfd;
#define MAXCON (maxfd - 10)
extern char *__progname;
fd_set *read_wait;
size_t read_wait_nfdset;
int ncon;
-struct ssh *active_state = NULL; /* XXX needed for linking */
-
/*
* Keep a connection structure for each file descriptor. The state
* associated with file descriptor n is held in fdcon[n].
*/
typedef struct Connection {
u_char c_status; /* State of connection on this file desc. */
#define CS_UNUSED 0 /* File descriptor unused */
#define CS_CON 1 /* Waiting to connect/read greeting */
#define CS_SIZE 2 /* Waiting to read initial packet size */
#define CS_KEYS 3 /* Waiting to read public key packet */
int c_fd; /* Quick lookup: c->c_fd == c - fdcon */
int c_plen; /* Packet length field for ssh packet */
int c_len; /* Total bytes which must be read. */
int c_off; /* Length of data read so far. */
int c_keytype; /* Only one of KT_* */
sig_atomic_t c_done; /* SSH2 done */
char *c_namebase; /* Address to free for c_name and c_namelist */
char *c_name; /* Hostname of connection for errors */
char *c_namelist; /* Pointer to other possible addresses */
char *c_output_name; /* Hostname of connection for output */
char *c_data; /* Data read from this fd */
struct ssh *c_ssh; /* SSH-connection */
struct timeval c_tv; /* Time at which connection gets aborted */
TAILQ_ENTRY(Connection) c_link; /* List of connections in timeout order. */
} con;
TAILQ_HEAD(conlist, Connection) tq; /* Timeout Queue */
con *fdcon;
static void keyprint(con *c, struct sshkey *key);
static int
fdlim_get(int hard)
{
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
struct rlimit rlfd;
if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
return (-1);
if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
return SSH_SYSFDMAX;
else
return hard ? rlfd.rlim_max : rlfd.rlim_cur;
#else
return SSH_SYSFDMAX;
#endif
}
static int
fdlim_set(int lim)
{
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
struct rlimit rlfd;
#endif
if (lim <= 0)
return (-1);
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
if (getrlimit(RLIMIT_NOFILE, &rlfd) < 0)
return (-1);
rlfd.rlim_cur = lim;
if (setrlimit(RLIMIT_NOFILE, &rlfd) < 0)
return (-1);
#elif defined (HAVE_SETDTABLESIZE)
setdtablesize(lim);
#endif
return (0);
}
/*
* This is an strsep function that returns a null field for adjacent
* separators. This is the same as the 4.4BSD strsep, but different from the
* one in the GNU libc.
*/
static char *
xstrsep(char **str, const char *delim)
{
char *s, *e;
if (!**str)
return (NULL);
s = *str;
e = s + strcspn(s, delim);
if (*e != '\0')
*e++ = '\0';
*str = e;
return (s);
}
/*
* Get the next non-null token (like GNU strsep). Strsep() will return a
* null token for two adjacent separators, so we may have to loop.
*/
static char *
strnnsep(char **stringp, char *delim)
{
char *tok;
do {
tok = xstrsep(stringp, delim);
} while (tok && *tok == '\0');
return (tok);
}
static int
key_print_wrapper(struct sshkey *hostkey, struct ssh *ssh)
{
con *c;
if ((c = ssh_get_app_data(ssh)) != NULL)
keyprint(c, hostkey);
/* always abort key exchange */
return -1;
}
static int
ssh2_capable(int remote_major, int remote_minor)
{
switch (remote_major) {
case 1:
if (remote_minor == 99)
return 1;
break;
case 2:
return 1;
default:
break;
}
return 0;
}
static void
keygrab_ssh2(con *c)
{
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
int r;
switch (c->c_keytype) {
case KT_DSA:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ssh-dss-cert-v01@openssh.com" : "ssh-dss";
break;
case KT_RSA:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ssh-rsa-cert-v01@openssh.com" : "ssh-rsa";
break;
case KT_ED25519:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519";
break;
case KT_XMSS:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ssh-xmss-cert-v01@openssh.com" : "ssh-xmss@openssh.com";
break;
case KT_ECDSA:
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ?
"ecdsa-sha2-nistp256-cert-v01@openssh.com,"
"ecdsa-sha2-nistp384-cert-v01@openssh.com,"
"ecdsa-sha2-nistp521-cert-v01@openssh.com" :
"ecdsa-sha2-nistp256,"
"ecdsa-sha2-nistp384,"
"ecdsa-sha2-nistp521";
break;
default:
fatal("unknown key type %d", c->c_keytype);
break;
}
if ((r = kex_setup(c->c_ssh, myproposal)) != 0) {
free(c->c_ssh);
fprintf(stderr, "kex_setup: %s\n", ssh_err(r));
exit(1);
}
#ifdef WITH_OPENSSL
- c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
- c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
- c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client;
- c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client;
- c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
c->c_ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
# ifdef OPENSSL_HAS_ECC
- c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+ c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
# endif
#endif
- c->c_ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
+ c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper);
/*
* do the key-exchange until an error occurs or until
* the key_print_wrapper() callback sets c_done.
*/
ssh_dispatch_run(c->c_ssh, DISPATCH_BLOCK, &c->c_done);
}
static void
keyprint_one(const char *host, struct sshkey *key)
{
char *hostport;
const char *known_host, *hashed;
+ found_one = 1;
+
if (print_sshfp) {
export_dns_rr(host, key, stdout, 0);
return;
}
hostport = put_host_port(host, ssh_port);
lowercase(hostport);
if (hash_hosts && (hashed = host_hash(host, NULL, 0)) == NULL)
fatal("host_hash failed");
known_host = hash_hosts ? hashed : hostport;
if (!get_cert)
fprintf(stdout, "%s ", known_host);
sshkey_write(key, stdout);
fputs("\n", stdout);
free(hostport);
}
static void
keyprint(con *c, struct sshkey *key)
{
char *hosts = c->c_output_name ? c->c_output_name : c->c_name;
char *host, *ohosts;
if (key == NULL)
return;
if (get_cert || (!hash_hosts && ssh_port == SSH_DEFAULT_PORT)) {
keyprint_one(hosts, key);
return;
}
ohosts = hosts = xstrdup(hosts);
while ((host = strsep(&hosts, ",")) != NULL)
keyprint_one(host, key);
free(ohosts);
}
static int
tcpconnect(char *host)
{
struct addrinfo hints, *ai, *aitop;
char strport[NI_MAXSERV];
int gaierr, s = -1;
snprintf(strport, sizeof strport, "%d", ssh_port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
error("getaddrinfo %s: %s", host, ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (s < 0) {
error("socket: %s", strerror(errno));
continue;
}
if (set_nonblock(s) == -1)
fatal("%s: set_nonblock(%d)", __func__, s);
if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0 &&
errno != EINPROGRESS)
error("connect (`%s'): %s", host, strerror(errno));
else
break;
close(s);
s = -1;
}
freeaddrinfo(aitop);
return s;
}
static int
conalloc(char *iname, char *oname, int keytype)
{
char *namebase, *name, *namelist;
int s;
namebase = namelist = xstrdup(iname);
do {
name = xstrsep(&namelist, ",");
if (!name) {
free(namebase);
return (-1);
}
} while ((s = tcpconnect(name)) < 0);
if (s >= maxfd)
fatal("conalloc: fdno %d too high", s);
if (fdcon[s].c_status)
fatal("conalloc: attempt to reuse fdno %d", s);
debug3("%s: oname %s kt %d", __func__, oname, keytype);
fdcon[s].c_fd = s;
fdcon[s].c_status = CS_CON;
fdcon[s].c_namebase = namebase;
fdcon[s].c_name = name;
fdcon[s].c_namelist = namelist;
fdcon[s].c_output_name = xstrdup(oname);
fdcon[s].c_data = (char *) &fdcon[s].c_plen;
fdcon[s].c_len = 4;
fdcon[s].c_off = 0;
fdcon[s].c_keytype = keytype;
monotime_tv(&fdcon[s].c_tv);
fdcon[s].c_tv.tv_sec += timeout;
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
FD_SET(s, read_wait);
ncon++;
return (s);
}
static void
confree(int s)
{
if (s >= maxfd || fdcon[s].c_status == CS_UNUSED)
fatal("confree: attempt to free bad fdno %d", s);
free(fdcon[s].c_namebase);
free(fdcon[s].c_output_name);
if (fdcon[s].c_status == CS_KEYS)
free(fdcon[s].c_data);
fdcon[s].c_status = CS_UNUSED;
fdcon[s].c_keytype = 0;
if (fdcon[s].c_ssh) {
ssh_packet_close(fdcon[s].c_ssh);
free(fdcon[s].c_ssh);
fdcon[s].c_ssh = NULL;
} else
close(s);
TAILQ_REMOVE(&tq, &fdcon[s], c_link);
FD_CLR(s, read_wait);
ncon--;
}
static void
contouch(int s)
{
TAILQ_REMOVE(&tq, &fdcon[s], c_link);
monotime_tv(&fdcon[s].c_tv);
fdcon[s].c_tv.tv_sec += timeout;
TAILQ_INSERT_TAIL(&tq, &fdcon[s], c_link);
}
static int
conrecycle(int s)
{
con *c = &fdcon[s];
int ret;
ret = conalloc(c->c_namelist, c->c_output_name, c->c_keytype);
confree(s);
return (ret);
}
static void
congreet(int s)
{
int n = 0, remote_major = 0, remote_minor = 0;
char buf[256], *cp;
char remote_version[sizeof buf];
size_t bufsiz;
con *c = &fdcon[s];
/* send client banner */
n = snprintf(buf, sizeof buf, "SSH-%d.%d-OpenSSH-keyscan\r\n",
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
if (n < 0 || (size_t)n >= sizeof(buf)) {
error("snprintf: buffer too small");
confree(s);
return;
}
if (atomicio(vwrite, s, buf, n) != (size_t)n) {
error("write (%s): %s", c->c_name, strerror(errno));
confree(s);
return;
}
for (;;) {
memset(buf, '\0', sizeof(buf));
bufsiz = sizeof(buf);
cp = buf;
while (bufsiz-- &&
(n = atomicio(read, s, cp, 1)) == 1 && *cp != '\n') {
if (*cp == '\r')
*cp = '\n';
cp++;
}
if (n != 1 || strncmp(buf, "SSH-", 4) == 0)
break;
}
if (n == 0) {
switch (errno) {
case EPIPE:
error("%s: Connection closed by remote host", c->c_name);
break;
case ECONNREFUSED:
break;
default:
error("read (%s): %s", c->c_name, strerror(errno));
break;
}
conrecycle(s);
return;
}
if (*cp != '\n' && *cp != '\r') {
error("%s: bad greeting", c->c_name);
confree(s);
return;
}
*cp = '\0';
if ((c->c_ssh = ssh_packet_set_connection(NULL, s, s)) == NULL)
fatal("ssh_packet_set_connection failed");
ssh_packet_set_timeout(c->c_ssh, timeout, 1);
ssh_set_app_data(c->c_ssh, c); /* back link */
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
&remote_major, &remote_minor, remote_version) == 3)
c->c_ssh->compat = compat_datafellows(remote_version);
else
c->c_ssh->compat = 0;
if (!ssh2_capable(remote_major, remote_minor)) {
debug("%s doesn't support ssh2", c->c_name);
confree(s);
return;
}
fprintf(stderr, "%c %s:%d %s\n", print_sshfp ? ';' : '#',
c->c_name, ssh_port, chop(buf));
keygrab_ssh2(c);
confree(s);
}
static void
conread(int s)
{
con *c = &fdcon[s];
size_t n;
if (c->c_status == CS_CON) {
congreet(s);
return;
}
n = atomicio(read, s, c->c_data + c->c_off, c->c_len - c->c_off);
if (n == 0) {
error("read (%s): %s", c->c_name, strerror(errno));
confree(s);
return;
}
c->c_off += n;
if (c->c_off == c->c_len)
switch (c->c_status) {
case CS_SIZE:
c->c_plen = htonl(c->c_plen);
c->c_len = c->c_plen + 8 - (c->c_plen & 7);
c->c_off = 0;
c->c_data = xmalloc(c->c_len);
c->c_status = CS_KEYS;
break;
default:
fatal("conread: invalid status %d", c->c_status);
break;
}
contouch(s);
}
static void
conloop(void)
{
struct timeval seltime, now;
fd_set *r, *e;
con *c;
int i;
monotime_tv(&now);
c = TAILQ_FIRST(&tq);
if (c && (c->c_tv.tv_sec > now.tv_sec ||
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) {
seltime = c->c_tv;
seltime.tv_sec -= now.tv_sec;
seltime.tv_usec -= now.tv_usec;
if (seltime.tv_usec < 0) {
seltime.tv_usec += 1000000;
seltime.tv_sec--;
}
} else
timerclear(&seltime);
r = xcalloc(read_wait_nfdset, sizeof(fd_mask));
e = xcalloc(read_wait_nfdset, sizeof(fd_mask));
memcpy(r, read_wait, read_wait_nfdset * sizeof(fd_mask));
memcpy(e, read_wait, read_wait_nfdset * sizeof(fd_mask));
while (select(maxfd, r, NULL, e, &seltime) == -1 &&
(errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
;
for (i = 0; i < maxfd; i++) {
if (FD_ISSET(i, e)) {
error("%s: exception!", fdcon[i].c_name);
confree(i);
} else if (FD_ISSET(i, r))
conread(i);
}
free(r);
free(e);
c = TAILQ_FIRST(&tq);
while (c && (c->c_tv.tv_sec < now.tv_sec ||
(c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) {
int s = c->c_fd;
c = TAILQ_NEXT(c, c_link);
conrecycle(s);
}
}
static void
do_host(char *host)
{
char *name = strnnsep(&host, " \t\n");
int j;
if (name == NULL)
return;
for (j = KT_MIN; j <= KT_MAX; j *= 2) {
if (get_keytypes & j) {
while (ncon >= MAXCON)
conloop();
conalloc(name, *host ? host : name, j);
}
}
}
void
fatal(const char *fmt,...)
{
va_list args;
va_start(args, fmt);
do_log(SYSLOG_LEVEL_FATAL, fmt, args);
va_end(args);
exit(255);
}
static void
usage(void)
{
fprintf(stderr,
"usage: %s [-46cDHv] [-f file] [-p port] [-T timeout] [-t type]\n"
"\t\t [host | addrlist namelist]\n",
__progname);
exit(1);
}
int
main(int argc, char **argv)
{
int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
int opt, fopt_count = 0, j;
char *tname, *cp, *line = NULL;
size_t linesize = 0;
FILE *fp;
extern int optind;
extern char *optarg;
ssh_malloc_init(); /* must be called before any mallocs */
__progname = ssh_get_progname(argv[0]);
seed_rng();
TAILQ_INIT(&tq);
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
if (argc <= 1)
usage();
while ((opt = getopt(argc, argv, "cDHv46p:T:t:f:")) != -1) {
switch (opt) {
case 'H':
hash_hosts = 1;
break;
case 'c':
get_cert = 1;
break;
case 'D':
print_sshfp = 1;
break;
case 'p':
ssh_port = a2port(optarg);
if (ssh_port <= 0) {
fprintf(stderr, "Bad port '%s'\n", optarg);
exit(1);
}
break;
case 'T':
timeout = convtime(optarg);
if (timeout == -1 || timeout == 0) {
fprintf(stderr, "Bad timeout '%s'\n", optarg);
usage();
}
break;
case 'v':
if (!debug_flag) {
debug_flag = 1;
log_level = SYSLOG_LEVEL_DEBUG1;
}
else if (log_level < SYSLOG_LEVEL_DEBUG3)
log_level++;
else
fatal("Too high debugging level.");
break;
case 'f':
if (strcmp(optarg, "-") == 0)
optarg = NULL;
argv[fopt_count++] = optarg;
break;
case 't':
get_keytypes = 0;
tname = strtok(optarg, ",");
while (tname) {
int type = sshkey_type_from_name(tname);
switch (type) {
case KEY_DSA:
get_keytypes |= KT_DSA;
break;
case KEY_ECDSA:
get_keytypes |= KT_ECDSA;
break;
case KEY_RSA:
get_keytypes |= KT_RSA;
break;
case KEY_ED25519:
get_keytypes |= KT_ED25519;
break;
case KEY_XMSS:
get_keytypes |= KT_XMSS;
break;
case KEY_UNSPEC:
default:
fatal("Unknown key type \"%s\"", tname);
}
tname = strtok(NULL, ",");
}
break;
case '4':
IPv4or6 = AF_INET;
break;
case '6':
IPv4or6 = AF_INET6;
break;
case '?':
default:
usage();
}
}
if (optind == argc && !fopt_count)
usage();
log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1);
maxfd = fdlim_get(1);
if (maxfd < 0)
fatal("%s: fdlim_get: bad value", __progname);
if (maxfd > MAXMAXFD)
maxfd = MAXMAXFD;
if (MAXCON <= 0)
fatal("%s: not enough file descriptors", __progname);
if (maxfd > fdlim_get(0))
fdlim_set(maxfd);
fdcon = xcalloc(maxfd, sizeof(con));
read_wait_nfdset = howmany(maxfd, NFDBITS);
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
for (j = 0; j < fopt_count; j++) {
if (argv[j] == NULL)
fp = stdin;
else if ((fp = fopen(argv[j], "r")) == NULL)
fatal("%s: %s: %s", __progname, argv[j],
strerror(errno));
while (getline(&line, &linesize, fp) != -1) {
/* Chomp off trailing whitespace and comments */
if ((cp = strchr(line, '#')) == NULL)
cp = line + strlen(line) - 1;
while (cp >= line) {
if (*cp == ' ' || *cp == '\t' ||
*cp == '\n' || *cp == '#')
*cp-- = '\0';
else
break;
}
/* Skip empty lines */
if (*line == '\0')
continue;
do_host(line);
}
if (ferror(fp))
fatal("%s: %s: %s", __progname, argv[j],
strerror(errno));
fclose(fp);
}
free(line);
while (optind < argc)
do_host(argv[optind++]);
while (ncon > 0)
conloop();
- return (0);
+ return found_one ? 0 : 1;
}
diff --git a/ssh-keysign.0 b/ssh-keysign.0
index db4355d297cc..172739ebde11 100644
--- a/ssh-keysign.0
+++ b/ssh-keysign.0
@@ -1,52 +1,52 @@
SSH-KEYSIGN(8) System Manager's Manual SSH-KEYSIGN(8)
NAME
ssh-keysign M-bM-^@M-^S ssh helper program for host-based authentication
SYNOPSIS
ssh-keysign
DESCRIPTION
ssh-keysign is used by ssh(1) to access the local host keys and generate
the digital signature required during host-based authentication.
ssh-keysign is disabled by default and can only be enabled in the global
client configuration file /etc/ssh/ssh_config by setting EnableSSHKeysign
to M-bM-^@M-^\yesM-bM-^@M-^].
ssh-keysign is not intended to be invoked by the user, but from ssh(1).
See ssh(1) and sshd(8) for more information about host-based
authentication.
FILES
/etc/ssh/ssh_config
Controls whether ssh-keysign is enabled.
/etc/ssh/ssh_host_dsa_key
/etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_rsa_key
These files contain the private parts of the host keys used to
generate the digital signature. They should be owned by root,
readable only by root, and not accessible to others. Since they
are readable only by root, ssh-keysign must be set-uid root if
host-based authentication is used.
/etc/ssh/ssh_host_dsa_key-cert.pub
/etc/ssh/ssh_host_ecdsa_key-cert.pub
/etc/ssh/ssh_host_ed25519_key-cert.pub
/etc/ssh/ssh_host_rsa_key-cert.pub
If these files exist they are assumed to contain public
certificate information corresponding with the private keys
above.
SEE ALSO
ssh(1), ssh-keygen(1), ssh_config(5), sshd(8)
HISTORY
ssh-keysign first appeared in OpenBSD 3.2.
AUTHORS
Markus Friedl <markus@openbsd.org>
-OpenBSD 6.4 February 17, 2016 OpenBSD 6.4
+OpenBSD 6.5 February 17, 2016 OpenBSD 6.5
diff --git a/ssh-keysign.c b/ssh-keysign.c
index 744ecb4f90f3..601f6ca72740 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -1,303 +1,294 @@
-/* $OpenBSD: ssh-keysign.c,v 1.55 2018/07/27 05:34:42 dtucker Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.56 2018/11/23 05:08:07 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <fcntl.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
+#include "openbsd-compat/openssl-compat.h"
#endif
#include "xmalloc.h"
#include "log.h"
#include "sshkey.h"
#include "ssh.h"
#include "ssh2.h"
#include "misc.h"
#include "sshbuf.h"
#include "authfile.h"
#include "msg.h"
#include "canohost.h"
#include "pathnames.h"
#include "readconf.h"
#include "uidswap.h"
#include "sshkey.h"
#include "ssherr.h"
-struct ssh *active_state = NULL; /* XXX needed for linking */
-
extern char *__progname;
static int
valid_request(struct passwd *pw, char *host, struct sshkey **ret,
u_char *data, size_t datalen)
{
struct sshbuf *b;
struct sshkey *key = NULL;
u_char type, *pkblob;
char *p;
size_t blen, len;
char *pkalg, *luser;
int r, pktype, fail;
if (ret != NULL)
*ret = NULL;
fail = 0;
if ((b = sshbuf_from(data, datalen)) == NULL)
fatal("%s: sshbuf_from failed", __func__);
/* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */
if ((r = sshbuf_get_string(b, NULL, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (len != 20 && len != 32)
fail++;
if ((r = sshbuf_get_u8(b, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
/* server user */
if ((r = sshbuf_skip_string(b)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
/* service */
if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp("ssh-connection", p) != 0)
fail++;
free(p);
/* method */
if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp("hostbased", p) != 0)
fail++;
free(p);
/* pubkey */
if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 ||
(r = sshbuf_get_string(b, &pkblob, &blen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC)
fail++;
else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
error("%s: bad key blob: %s", __func__, ssh_err(r));
fail++;
} else if (key->type != pktype)
fail++;
free(pkalg);
free(pkblob);
/* client host name, handle trailing dot */
if ((r = sshbuf_get_cstring(b, &p, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
debug2("%s: check expect chost %s got %s", __func__, host, p);
if (strlen(host) != len - 1)
fail++;
else if (p[len - 1] != '.')
fail++;
else if (strncasecmp(host, p, len - 1) != 0)
fail++;
free(p);
/* local user */
if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (strcmp(pw->pw_name, luser) != 0)
fail++;
free(luser);
/* end of message */
if (sshbuf_len(b) != 0)
fail++;
sshbuf_free(b);
debug3("%s: fail %d", __func__, fail);
if (fail)
sshkey_free(key);
else if (ret != NULL)
*ret = key;
return (fail ? -1 : 0);
}
int
main(int argc, char **argv)
{
struct sshbuf *b;
Options options;
#define NUM_KEYTYPES 5
struct sshkey *keys[NUM_KEYTYPES], *key = NULL;
struct passwd *pw;
int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
u_char *signature, *data, rver;
char *host, *fp;
size_t slen, dlen;
-#ifdef WITH_OPENSSL
- u_int32_t rnd[256];
-#endif
ssh_malloc_init(); /* must be called before any mallocs */
if (pledge("stdio rpath getpw dns id", NULL) != 0)
fatal("%s: pledge: %s", __progname, strerror(errno));
/* Ensure that stdin and stdout are connected */
if ((fd = open(_PATH_DEVNULL, O_RDWR)) < 2)
exit(1);
/* Leave /dev/null fd iff it is attached to stderr */
if (fd > 2)
close(fd);
i = 0;
/* XXX This really needs to read sshd_config for the paths */
key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY);
key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
if ((pw = getpwuid(getuid())) == NULL)
fatal("getpwuid failed");
pw = pwcopy(pw);
permanently_set_uid(pw);
seed_rng();
#ifdef DEBUG_SSH_KEYSIGN
log_init("ssh-keysign", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 0);
#endif
/* verify that ssh-keysign is enabled by the admin */
initialize_options(&options);
- (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0);
+ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "",
+ &options, 0, NULL);
fill_default_options(&options);
if (options.enable_ssh_keysign != 1)
fatal("ssh-keysign not enabled in %s",
_PATH_HOST_CONFIG_FILE);
for (i = found = 0; i < NUM_KEYTYPES; i++) {
if (key_fd[i] != -1)
found = 1;
}
if (found == 0)
fatal("could not open any host key");
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
- arc4random_buf(rnd, sizeof(rnd));
- RAND_seed(rnd, sizeof(rnd));
-#endif
-
found = 0;
for (i = 0; i < NUM_KEYTYPES; i++) {
keys[i] = NULL;
if (key_fd[i] == -1)
continue;
r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC,
NULL, &key, NULL);
close(key_fd[i]);
if (r != 0)
debug("parse key %d: %s", i, ssh_err(r));
else if (key != NULL) {
keys[i] = key;
found = 1;
}
}
if (!found)
fatal("no hostkey found");
if (pledge("stdio dns", NULL) != 0)
fatal("%s: pledge: %s", __progname, strerror(errno));
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __progname);
if (ssh_msg_recv(STDIN_FILENO, b) < 0)
fatal("ssh_msg_recv failed");
if ((r = sshbuf_get_u8(b, &rver)) != 0)
fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (rver != version)
fatal("bad version: received %d, expected %d", rver, version);
if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0)
fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO)
fatal("bad fd");
if ((host = get_local_name(fd)) == NULL)
fatal("cannot get local name for fd");
if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (valid_request(pw, host, &key, data, dlen) < 0)
fatal("not a valid request");
free(host);
found = 0;
for (i = 0; i < NUM_KEYTYPES; i++) {
if (keys[i] != NULL &&
sshkey_equal_public(key, keys[i])) {
found = 1;
break;
}
}
if (!found) {
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __progname);
fatal("no matching hostkey found for key %s %s",
sshkey_type(key), fp ? fp : "");
}
if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, NULL, 0))
!= 0)
fatal("sshkey_sign failed: %s", ssh_err(r));
free(data);
/* send reply */
sshbuf_reset(b);
if ((r = sshbuf_put_string(b, signature, slen)) != 0)
fatal("%s: buffer error: %s", __progname, ssh_err(r));
if (ssh_msg_send(STDOUT_FILENO, version, b) == -1)
fatal("ssh_msg_send failed");
return (0);
}
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
index d1241ce67f32..e7860de89815 100644
--- a/ssh-pkcs11-client.c
+++ b/ssh-pkcs11-client.c
@@ -1,269 +1,384 @@
-/* $OpenBSD: ssh-pkcs11-client.c,v 1.10 2018/07/09 21:59:10 markus Exp $ */
+/* $OpenBSD: ssh-pkcs11-client.c,v 1.15 2019/01/21 12:53:35 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
+ * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef ENABLE_PKCS11
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <sys/socket.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <openssl/ecdsa.h>
#include <openssl/rsa.h>
#include "openbsd-compat/openssl-compat.h"
#include "pathnames.h"
#include "xmalloc.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "sshkey.h"
#include "authfd.h"
#include "atomicio.h"
#include "ssh-pkcs11.h"
#include "ssherr.h"
/* borrows code from sftp-server and ssh-agent */
-int fd = -1;
-pid_t pid = -1;
+static int fd = -1;
+static pid_t pid = -1;
static void
send_msg(struct sshbuf *m)
{
u_char buf[4];
size_t mlen = sshbuf_len(m);
int r;
POKE_U32(buf, mlen);
if (atomicio(vwrite, fd, buf, 4) != 4 ||
atomicio(vwrite, fd, sshbuf_mutable_ptr(m),
sshbuf_len(m)) != sshbuf_len(m))
error("write to helper failed");
if ((r = sshbuf_consume(m, mlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
static int
recv_msg(struct sshbuf *m)
{
u_int l, len;
u_char c, buf[1024];
int r;
if ((len = atomicio(read, fd, buf, 4)) != 4) {
error("read from helper failed: %u", len);
return (0); /* XXX */
}
len = PEEK_U32(buf);
if (len > 256 * 1024)
fatal("response too long: %u", len);
/* read len bytes into m */
sshbuf_reset(m);
while (len > 0) {
l = len;
if (l > sizeof(buf))
l = sizeof(buf);
if (atomicio(read, fd, buf, l) != l) {
error("response from helper failed.");
return (0); /* XXX */
}
if ((r = sshbuf_put(m, buf, l)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
len -= l;
}
if ((r = sshbuf_get_u8(m, &c)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
return c;
}
int
pkcs11_init(int interactive)
{
return (0);
}
void
pkcs11_terminate(void)
{
if (fd >= 0)
close(fd);
}
static int
-pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
- int padding)
+rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
{
- struct sshkey key; /* XXX */
- u_char *blob, *signature = NULL;
+ struct sshkey *key = NULL;
+ struct sshbuf *msg = NULL;
+ u_char *blob = NULL, *signature = NULL;
size_t blen, slen = 0;
int r, ret = -1;
- struct sshbuf *msg;
if (padding != RSA_PKCS1_PADDING)
- return (-1);
- key.type = KEY_RSA;
- key.rsa = rsa;
- if ((r = sshkey_to_blob(&key, &blob, &blen)) != 0) {
+ goto fail;
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("%s: sshkey_new failed", __func__);
+ goto fail;
+ }
+ key->type = KEY_RSA;
+ RSA_up_ref(rsa);
+ key->rsa = rsa;
+ if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
- return -1;
+ goto fail;
}
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_string(msg, from, flen)) != 0 ||
(r = sshbuf_put_u32(msg, 0)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- free(blob);
send_msg(msg);
sshbuf_reset(msg);
if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (slen <= (size_t)RSA_size(rsa)) {
memcpy(to, signature, slen);
ret = slen;
}
free(signature);
}
+ fail:
+ free(blob);
+ sshkey_free(key);
+ sshbuf_free(msg);
+ return (ret);
+}
+
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static ECDSA_SIG *
+ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
+ const BIGNUM *rp, EC_KEY *ec)
+{
+ struct sshkey *key = NULL;
+ struct sshbuf *msg = NULL;
+ ECDSA_SIG *ret = NULL;
+ const u_char *cp;
+ u_char *blob = NULL, *signature = NULL;
+ size_t blen, slen = 0;
+ int r, nid;
+
+ nid = sshkey_ecdsa_key_to_nid(ec);
+ if (nid < 0) {
+ error("%s: couldn't get curve nid", __func__);
+ goto fail;
+ }
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("%s: sshkey_new failed", __func__);
+ goto fail;
+ }
+ key->ecdsa = ec;
+ key->ecdsa_nid = nid;
+ key->type = KEY_ECDSA;
+ EC_KEY_up_ref(ec);
+
+ if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
+ error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
+ goto fail;
+ }
+ if ((msg = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
+ (r = sshbuf_put_string(msg, blob, blen)) != 0 ||
+ (r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
+ (r = sshbuf_put_u32(msg, 0)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ send_msg(msg);
+ sshbuf_reset(msg);
+
+ if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
+ if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ cp = signature;
+ ret = d2i_ECDSA_SIG(NULL, &cp, slen);
+ free(signature);
+ }
+
+ fail:
+ free(blob);
+ sshkey_free(key);
sshbuf_free(msg);
return (ret);
}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+static RSA_METHOD *helper_rsa;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static EC_KEY_METHOD *helper_ecdsa;
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+/* redirect private key crypto operations to the ssh-pkcs11-helper */
+static void
+wrap_key(struct sshkey *k)
+{
+ if (k->type == KEY_RSA)
+ RSA_set_method(k->rsa, helper_rsa);
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ else if (k->type == KEY_ECDSA)
+ EC_KEY_set_method(k->ecdsa, helper_ecdsa);
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+ else
+ fatal("%s: unknown key type", __func__);
+}
-/* redirect the private key encrypt operation to the ssh-pkcs11-helper */
static int
-wrap_key(RSA *rsa)
+pkcs11_start_helper_methods(void)
{
- static RSA_METHOD *helper_rsa;
+ if (helper_rsa != NULL)
+ return (0);
+
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
+ if (helper_ecdsa != NULL)
+ return (0);
+ helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
+ if (helper_ecdsa == NULL)
+ return (-1);
+ EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
+ EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
+#endif /* HAVE_EC_KEY_METHOD_NEW */
if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
fatal("%s: RSA_meth_dup failed", __func__);
if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") ||
- !RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt))
+ !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt))
fatal("%s: failed to prepare method", __func__);
- RSA_set_method(rsa, helper_rsa);
+
return (0);
}
static int
pkcs11_start_helper(void)
{
int pair[2];
+ char *helper, *verbosity = NULL;
+
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
+ verbosity = "-vvv";
+
+ if (pkcs11_start_helper_methods() == -1) {
+ error("pkcs11_start_helper_methods failed");
+ return (-1);
+ }
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
error("socketpair: %s", strerror(errno));
return (-1);
}
if ((pid = fork()) == -1) {
error("fork: %s", strerror(errno));
return (-1);
} else if (pid == 0) {
if ((dup2(pair[1], STDIN_FILENO) == -1) ||
(dup2(pair[1], STDOUT_FILENO) == -1)) {
fprintf(stderr, "dup2: %s\n", strerror(errno));
_exit(1);
}
close(pair[0]);
close(pair[1]);
- execlp(_PATH_SSH_PKCS11_HELPER, _PATH_SSH_PKCS11_HELPER,
- (char *)NULL);
- fprintf(stderr, "exec: %s: %s\n", _PATH_SSH_PKCS11_HELPER,
- strerror(errno));
+ helper = getenv("SSH_PKCS11_HELPER");
+ if (helper == NULL || strlen(helper) == 0)
+ helper = _PATH_SSH_PKCS11_HELPER;
+ debug("%s: starting %s %s", __func__, helper,
+ verbosity == NULL ? "" : verbosity);
+ execlp(helper, helper, verbosity, (char *)NULL);
+ fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno));
_exit(1);
}
close(pair[1]);
fd = pair[0];
return (0);
}
int
pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp)
{
struct sshkey *k;
- int r;
+ int r, type;
u_char *blob;
size_t blen;
u_int nkeys, i;
struct sshbuf *msg;
if (fd < 0 && pkcs11_start_helper() < 0)
return (-1);
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 ||
(r = sshbuf_put_cstring(msg, name)) != 0 ||
(r = sshbuf_put_cstring(msg, pin)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
sshbuf_reset(msg);
- if (recv_msg(msg) == SSH2_AGENT_IDENTITIES_ANSWER) {
+ type = recv_msg(msg);
+ if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
*keysp = xcalloc(nkeys, sizeof(struct sshkey *));
for (i = 0; i < nkeys; i++) {
/* XXX clean up properly instead of fatal() */
if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
(r = sshbuf_skip_string(msg)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
fatal("%s: bad key: %s", __func__, ssh_err(r));
- wrap_key(k->rsa);
+ wrap_key(k);
(*keysp)[i] = k;
free(blob);
}
+ } else if (type == SSH2_AGENT_FAILURE) {
+ if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
+ nkeys = -1;
} else {
nkeys = -1;
}
sshbuf_free(msg);
return (nkeys);
}
int
pkcs11_del_provider(char *name)
{
int r, ret = -1;
struct sshbuf *msg;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 ||
(r = sshbuf_put_cstring(msg, name)) != 0 ||
(r = sshbuf_put_cstring(msg, "")) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
send_msg(msg);
sshbuf_reset(msg);
if (recv_msg(msg) == SSH_AGENT_SUCCESS)
ret = 0;
sshbuf_free(msg);
return (ret);
}
#endif /* ENABLE_PKCS11 */
diff --git a/ssh-pkcs11-helper.0 b/ssh-pkcs11-helper.0
index 4d5c9843b89c..22f690717a70 100644
--- a/ssh-pkcs11-helper.0
+++ b/ssh-pkcs11-helper.0
@@ -1,25 +1,35 @@
SSH-PKCS11-HELPER(8) System Manager's Manual SSH-PKCS11-HELPER(8)
NAME
ssh-pkcs11-helper M-bM-^@M-^S ssh-agent helper program for PKCS#11 support
SYNOPSIS
- ssh-pkcs11-helper
+ ssh-pkcs11-helper [-v]
DESCRIPTION
ssh-pkcs11-helper is used by ssh-agent(1) to access keys provided by a
PKCS#11 token.
ssh-pkcs11-helper is not intended to be invoked by the user, but from
ssh-agent(1).
+ A single option is supported:
+
+ -v Verbose mode. Causes ssh-pkcs11-helper to print debugging
+ messages about its progress. This is helpful in debugging
+ problems. Multiple -v options increase the verbosity. The
+ maximum is 3.
+
+ Note that ssh-agent(1) will automatically pass the -v flag to
+ ssh-pkcs11-helper when it has itself been placed in debug mode.
+
SEE ALSO
ssh(1), ssh-add(1), ssh-agent(1)
HISTORY
ssh-pkcs11-helper first appeared in OpenBSD 4.7.
AUTHORS
Markus Friedl <markus@openbsd.org>
-OpenBSD 6.4 July 16, 2013 OpenBSD 6.4
+OpenBSD 6.5 January 21, 2019 OpenBSD 6.5
diff --git a/ssh-pkcs11-helper.8 b/ssh-pkcs11-helper.8
index 3728c4e4e7e4..ba5c30fa0525 100644
--- a/ssh-pkcs11-helper.8
+++ b/ssh-pkcs11-helper.8
@@ -1,43 +1,66 @@
-.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.4 2013/07/16 00:07:52 schwarze Exp $
+.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.5 2019/01/21 12:53:35 djm Exp $
.\"
.\" Copyright (c) 2010 Markus Friedl. All rights reserved.
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: July 16 2013 $
+.Dd $Mdocdate: January 21 2019 $
.Dt SSH-PKCS11-HELPER 8
.Os
.Sh NAME
.Nm ssh-pkcs11-helper
.Nd ssh-agent helper program for PKCS#11 support
.Sh SYNOPSIS
.Nm
+.Op Fl v
.Sh DESCRIPTION
.Nm
is used by
.Xr ssh-agent 1
to access keys provided by a PKCS#11 token.
.Pp
.Nm
is not intended to be invoked by the user, but from
.Xr ssh-agent 1 .
+.Pp
+A single option is supported:
+.Bl -tag -width Ds
+.It Fl v
+Verbose mode.
+Causes
+.Nm
+to print debugging messages about its progress.
+This is helpful in debugging problems.
+Multiple
+.Fl v
+options increase the verbosity.
+The maximum is 3.
+.Pp
+Note that
+.Xr ssh-agent 1
+will automatically pass the
+.Fl v
+flag to
+.Nm
+when it has itself been placed in debug mode.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1
.Sh HISTORY
.Nm
first appeared in
.Ox 4.7 .
.Sh AUTHORS
.An Markus Friedl Aq Mt markus@openbsd.org
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index 6301033c513a..97fb1212c08e 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,402 +1,436 @@
-/* $OpenBSD: ssh-pkcs11-helper.c,v 1.14 2018/01/08 15:18:46 markus Exp $ */
+/* $OpenBSD: ssh-pkcs11-helper.c,v 1.17 2019/01/23 02:01:10 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include "openbsd-compat/sys-queue.h"
+#include <errno.h>
+#include <poll.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
-#include <errno.h>
#include "xmalloc.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
#include "sshkey.h"
#include "authfd.h"
#include "ssh-pkcs11.h"
#include "ssherr.h"
#ifdef ENABLE_PKCS11
/* borrows code from sftp-server and ssh-agent */
struct pkcs11_keyinfo {
struct sshkey *key;
char *providername;
TAILQ_ENTRY(pkcs11_keyinfo) next;
};
TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist;
#define MAX_MSG_LENGTH 10240 /*XXX*/
/* input and output queue */
struct sshbuf *iqueue;
struct sshbuf *oqueue;
static void
add_key(struct sshkey *k, char *name)
{
struct pkcs11_keyinfo *ki;
ki = xcalloc(1, sizeof(*ki));
ki->providername = xstrdup(name);
ki->key = k;
TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next);
}
static void
del_keys_by_name(char *name)
{
struct pkcs11_keyinfo *ki, *nxt;
for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) {
nxt = TAILQ_NEXT(ki, next);
if (!strcmp(ki->providername, name)) {
TAILQ_REMOVE(&pkcs11_keylist, ki, next);
free(ki->providername);
sshkey_free(ki->key);
free(ki);
}
}
}
/* lookup matching 'private' key */
static struct sshkey *
lookup_key(struct sshkey *k)
{
struct pkcs11_keyinfo *ki;
TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
debug("check %p %s", ki, ki->providername);
if (sshkey_equal(k, ki->key))
return (ki->key);
}
return (NULL);
}
static void
send_msg(struct sshbuf *m)
{
int r;
if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
static void
process_add(void)
{
char *name, *pin;
- struct sshkey **keys;
+ struct sshkey **keys = NULL;
int r, i, nkeys;
u_char *blob;
size_t blen;
struct sshbuf *msg;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) {
if ((r = sshbuf_put_u8(msg,
SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
(r = sshbuf_put_u32(msg, nkeys)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
for (i = 0; i < nkeys; i++) {
if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
debug("%s: sshkey_to_blob: %s",
__func__, ssh_err(r));
continue;
}
if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_cstring(msg, name)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
free(blob);
add_key(keys[i], name);
}
- free(keys);
} else {
if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
+ free(keys);
free(pin);
free(name);
send_msg(msg);
sshbuf_free(msg);
}
static void
process_del(void)
{
char *name, *pin;
struct sshbuf *msg;
int r;
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
del_keys_by_name(name);
if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
free(pin);
free(name);
send_msg(msg);
sshbuf_free(msg);
}
static void
process_sign(void)
{
u_char *blob, *data, *signature = NULL;
size_t blen, dlen, slen = 0;
int r, ok = -1;
struct sshkey *key, *found;
struct sshbuf *msg;
/* XXX support SHA2 signature flags */
if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
(r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
(r = sshbuf_get_u32(iqueue, NULL)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
else {
if ((found = lookup_key(key)) != NULL) {
#ifdef WITH_OPENSSL
+ u_int xslen;
int ret;
- slen = RSA_size(key->rsa);
- signature = xmalloc(slen);
- if ((ret = RSA_private_encrypt(dlen, data, signature,
- found->rsa, RSA_PKCS1_PADDING)) != -1) {
- slen = ret;
- ok = 0;
- }
+ if (key->type == KEY_RSA) {
+ slen = RSA_size(key->rsa);
+ signature = xmalloc(slen);
+ ret = RSA_private_encrypt(dlen, data, signature,
+ found->rsa, RSA_PKCS1_PADDING);
+ if (ret != -1) {
+ slen = ret;
+ ok = 0;
+ }
+ } else if (key->type == KEY_ECDSA) {
+ xslen = ECDSA_size(key->ecdsa);
+ signature = xmalloc(xslen);
+ /* "The parameter type is ignored." */
+ ret = ECDSA_sign(-1, data, dlen, signature,
+ &xslen, found->ecdsa);
+ if (ret != 0)
+ ok = 0;
+ else
+ error("%s: ECDSA_sign"
+ " returns %d", __func__, ret);
+ slen = xslen;
+ } else
+ error("%s: don't know how to sign with key "
+ "type %d", __func__, (int)key->type);
#endif /* WITH_OPENSSL */
}
sshkey_free(key);
}
if ((msg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (ok == 0) {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
} else {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
free(data);
free(blob);
free(signature);
send_msg(msg);
sshbuf_free(msg);
}
static void
process(void)
{
u_int msg_len;
u_int buf_len;
u_int consumed;
u_char type;
const u_char *cp;
int r;
buf_len = sshbuf_len(iqueue);
if (buf_len < 5)
return; /* Incomplete message. */
cp = sshbuf_ptr(iqueue);
msg_len = get_u32(cp);
if (msg_len > MAX_MSG_LENGTH) {
error("bad message len %d", msg_len);
cleanup_exit(11);
}
if (buf_len < msg_len + 4)
return;
if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
(r = sshbuf_get_u8(iqueue, &type)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
buf_len -= 4;
switch (type) {
case SSH_AGENTC_ADD_SMARTCARD_KEY:
debug("process_add");
process_add();
break;
case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
debug("process_del");
process_del();
break;
case SSH2_AGENTC_SIGN_REQUEST:
debug("process_sign");
process_sign();
break;
default:
error("Unknown message %d", type);
break;
}
/* discard the remaining bytes from the current packet */
if (buf_len < sshbuf_len(iqueue)) {
error("iqueue grew unexpectedly");
cleanup_exit(255);
}
consumed = buf_len - sshbuf_len(iqueue);
if (msg_len < consumed) {
error("msg_len %d < consumed %d", msg_len, consumed);
cleanup_exit(255);
}
if (msg_len > consumed) {
if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
}
void
cleanup_exit(int i)
{
/* XXX */
_exit(i);
}
+
int
main(int argc, char **argv)
{
- fd_set *rset, *wset;
- int r, in, out, max, log_stderr = 0;
- ssize_t len, olen, set_size;
+ int r, ch, in, out, max, log_stderr = 0;
+ ssize_t len;
SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
LogLevel log_level = SYSLOG_LEVEL_ERROR;
char buf[4*4096];
-
extern char *__progname;
+ struct pollfd pfd[2];
ssh_malloc_init(); /* must be called before any mallocs */
+ __progname = ssh_get_progname(argv[0]);
+ seed_rng();
TAILQ_INIT(&pkcs11_keylist);
- pkcs11_init(0);
- seed_rng();
- __progname = ssh_get_progname(argv[0]);
+ log_init(__progname, log_level, log_facility, log_stderr);
+
+ while ((ch = getopt(argc, argv, "v")) != -1) {
+ switch (ch) {
+ case 'v':
+ log_stderr = 1;
+ if (log_level == SYSLOG_LEVEL_ERROR)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-v]\n", __progname);
+ exit(1);
+ }
+ }
log_init(__progname, log_level, log_facility, log_stderr);
+ pkcs11_init(0);
+
in = STDIN_FILENO;
out = STDOUT_FILENO;
max = 0;
if (in > max)
max = in;
if (out > max)
max = out;
if ((iqueue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((oqueue = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
- rset = xmalloc(set_size);
- wset = xmalloc(set_size);
-
- for (;;) {
- memset(rset, 0, set_size);
- memset(wset, 0, set_size);
+ while (1) {
+ memset(pfd, 0, sizeof(pfd));
+ pfd[0].fd = in;
+ pfd[1].fd = out;
/*
* Ensure that we can read a full buffer and handle
* the worst-case length packet it can generate,
* otherwise apply backpressure by stopping reads.
*/
if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
(r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
- FD_SET(in, rset);
+ pfd[0].events = POLLIN;
else if (r != SSH_ERR_NO_BUFFER_SPACE)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
- olen = sshbuf_len(oqueue);
- if (olen > 0)
- FD_SET(out, wset);
+ if (sshbuf_len(oqueue) > 0)
+ pfd[1].events = POLLOUT;
- if (select(max+1, rset, wset, NULL, NULL) < 0) {
- if (errno == EINTR)
+ if ((r = poll(pfd, 2, -1 /* INFTIM */)) <= 0) {
+ if (r == 0 || errno == EINTR)
continue;
- error("select: %s", strerror(errno));
- cleanup_exit(2);
+ fatal("poll: %s", strerror(errno));
}
/* copy stdin to iqueue */
- if (FD_ISSET(in, rset)) {
+ if ((pfd[0].revents & (POLLIN|POLLERR)) != 0) {
len = read(in, buf, sizeof buf);
if (len == 0) {
debug("read eof");
cleanup_exit(0);
} else if (len < 0) {
error("read: %s", strerror(errno));
cleanup_exit(1);
} else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
/* send oqueue to stdout */
- if (FD_ISSET(out, wset)) {
- len = write(out, sshbuf_ptr(oqueue), olen);
+ if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) {
+ len = write(out, sshbuf_ptr(oqueue),
+ sshbuf_len(oqueue));
if (len < 0) {
error("write: %s", strerror(errno));
cleanup_exit(1);
} else if ((r = sshbuf_consume(oqueue, len)) != 0) {
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
/*
* Process requests from client if we can fit the results
* into the output buffer, otherwise stop processing input
* and let the output queue drain.
*/
if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
process();
else if (r != SSH_ERR_NO_BUFFER_SPACE)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
}
#else /* ENABLE_PKCS11 */
int
main(int argc, char **argv)
{
extern char *__progname;
__progname = ssh_get_progname(argv[0]);
log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0);
fatal("PKCS#11 support disabled at compile time");
}
#endif /* ENABLE_PKCS11 */
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 775de964210f..70f06bffe327 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,732 +1,1807 @@
-/* $OpenBSD: ssh-pkcs11.c,v 1.26 2018/02/07 02:06:51 jsing Exp $ */
+/* $OpenBSD: ssh-pkcs11.c,v 1.43 2019/03/08 17:24:43 markus Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
+ * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifdef ENABLE_PKCS11
-#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
+
+#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
+#include <ctype.h>
#include <string.h>
#include <dlfcn.h>
#include "openbsd-compat/sys-queue.h"
#include "openbsd-compat/openssl-compat.h"
+#include <openssl/ecdsa.h>
#include <openssl/x509.h>
+#include <openssl/err.h>
#define CRYPTOKI_COMPAT
#include "pkcs11.h"
#include "log.h"
#include "misc.h"
#include "sshkey.h"
#include "ssh-pkcs11.h"
#include "xmalloc.h"
struct pkcs11_slotinfo {
CK_TOKEN_INFO token;
CK_SESSION_HANDLE session;
int logged_in;
};
struct pkcs11_provider {
char *name;
void *handle;
CK_FUNCTION_LIST *function_list;
CK_INFO info;
CK_ULONG nslots;
CK_SLOT_ID *slotlist;
struct pkcs11_slotinfo *slotinfo;
int valid;
int refcount;
TAILQ_ENTRY(pkcs11_provider) next;
};
TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
struct pkcs11_key {
struct pkcs11_provider *provider;
CK_ULONG slotidx;
- int (*orig_finish)(RSA *rsa);
- RSA_METHOD *rsa_method;
char *keyid;
int keyid_len;
};
int pkcs11_interactive = 0;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static void
+ossl_error(const char *msg)
+{
+ unsigned long e;
+
+ error("%s: %s", __func__, msg);
+ while ((e = ERR_get_error()) != 0)
+ error("%s: libcrypto error: %.100s", __func__,
+ ERR_error_string(e, NULL));
+}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
int
pkcs11_init(int interactive)
{
pkcs11_interactive = interactive;
TAILQ_INIT(&pkcs11_providers);
return (0);
}
/*
- * finalize a provider shared libarary, it's no longer usable.
+ * finalize a provider shared library, it's no longer usable.
* however, there might still be keys referencing this provider,
- * so the actuall freeing of memory is handled by pkcs11_provider_unref().
+ * so the actual freeing of memory is handled by pkcs11_provider_unref().
* this is called when a provider gets unregistered.
*/
static void
pkcs11_provider_finalize(struct pkcs11_provider *p)
{
CK_RV rv;
CK_ULONG i;
debug("pkcs11_provider_finalize: %p refcount %d valid %d",
p, p->refcount, p->valid);
if (!p->valid)
return;
for (i = 0; i < p->nslots; i++) {
if (p->slotinfo[i].session &&
(rv = p->function_list->C_CloseSession(
p->slotinfo[i].session)) != CKR_OK)
error("C_CloseSession failed: %lu", rv);
}
if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK)
error("C_Finalize failed: %lu", rv);
p->valid = 0;
p->function_list = NULL;
dlclose(p->handle);
}
/*
* remove a reference to the provider.
* called when a key gets destroyed or when the provider is unregistered.
*/
static void
pkcs11_provider_unref(struct pkcs11_provider *p)
{
debug("pkcs11_provider_unref: %p refcount %d", p, p->refcount);
if (--p->refcount <= 0) {
if (p->valid)
error("pkcs11_provider_unref: %p still valid", p);
+ free(p->name);
free(p->slotlist);
free(p->slotinfo);
free(p);
}
}
/* unregister all providers, keys might still point to the providers */
void
pkcs11_terminate(void)
{
struct pkcs11_provider *p;
while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) {
TAILQ_REMOVE(&pkcs11_providers, p, next);
pkcs11_provider_finalize(p);
pkcs11_provider_unref(p);
}
}
/* lookup provider by name */
static struct pkcs11_provider *
pkcs11_provider_lookup(char *provider_id)
{
struct pkcs11_provider *p;
TAILQ_FOREACH(p, &pkcs11_providers, next) {
debug("check %p %s", p, p->name);
if (!strcmp(provider_id, p->name))
return (p);
}
return (NULL);
}
/* unregister provider by name */
int
pkcs11_del_provider(char *provider_id)
{
struct pkcs11_provider *p;
if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
TAILQ_REMOVE(&pkcs11_providers, p, next);
pkcs11_provider_finalize(p);
pkcs11_provider_unref(p);
return (0);
}
return (-1);
}
-/* openssl callback for freeing an RSA key */
-static int
-pkcs11_rsa_finish(RSA *rsa)
+static RSA_METHOD *rsa_method;
+static int rsa_idx = 0;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static EC_KEY_METHOD *ec_key_method;
+static int ec_key_idx = 0;
+#endif
+
+/* release a wrapped object */
+static void
+pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
+ long argl, void *argp)
{
- struct pkcs11_key *k11;
- int rv = -1;
+ struct pkcs11_key *k11 = ptr;
- if ((k11 = RSA_get_app_data(rsa)) != NULL) {
- if (k11->orig_finish)
- rv = k11->orig_finish(rsa);
- if (k11->provider)
- pkcs11_provider_unref(k11->provider);
- RSA_meth_free(k11->rsa_method);
- free(k11->keyid);
- free(k11);
- }
- return (rv);
+ debug("%s: parent %p ptr %p idx %d", __func__, parent, ptr, idx);
+ if (k11 == NULL)
+ return;
+ if (k11->provider)
+ pkcs11_provider_unref(k11->provider);
+ free(k11->keyid);
+ free(k11);
}
/* find a single 'obj' for given attributes */
static int
pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
CK_ULONG nattr, CK_OBJECT_HANDLE *obj)
{
CK_FUNCTION_LIST *f;
CK_SESSION_HANDLE session;
CK_ULONG nfound = 0;
CK_RV rv;
int ret = -1;
f = p->function_list;
session = p->slotinfo[slotidx].session;
if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) {
error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv);
return (-1);
}
if ((rv = f->C_FindObjects(session, obj, 1, &nfound)) != CKR_OK ||
nfound != 1) {
debug("C_FindObjects failed (nfound %lu nattr %lu): %lu",
nfound, nattr, rv);
} else
ret = 0;
if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
error("C_FindObjectsFinal failed: %lu", rv);
return (ret);
}
-/* openssl callback doing the actual signing operation */
static int
-pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
- int padding)
+pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
{
- struct pkcs11_key *k11;
struct pkcs11_slotinfo *si;
CK_FUNCTION_LIST *f;
- CK_OBJECT_HANDLE obj;
- CK_ULONG tlen = 0;
- CK_RV rv;
- CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
- CK_BBOOL true_val = CK_TRUE;
- CK_MECHANISM mech = {
- CKM_RSA_PKCS, NULL_PTR, 0
- };
- CK_ATTRIBUTE key_filter[] = {
- {CKA_CLASS, NULL, sizeof(private_key_class) },
- {CKA_ID, NULL, 0},
- {CKA_SIGN, NULL, sizeof(true_val) }
- };
char *pin = NULL, prompt[1024];
- int rval = -1;
+ CK_RV rv;
- key_filter[0].pValue = &private_key_class;
- key_filter[2].pValue = &true_val;
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider found");
+ return (-1);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ if (!pkcs11_interactive) {
+ error("need pin entry%s",
+ (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
+ " on reader keypad" : "");
+ return (-1);
+ }
+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
+ verbose("Deferring PIN entry to reader keypad.");
+ else {
+ snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
+ si->token.label);
+ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
+ debug("%s: no pin specified", __func__);
+ return (-1); /* bail out */
+ }
+ }
+ rv = f->C_Login(si->session, type, (u_char *)pin,
+ (pin != NULL) ? strlen(pin) : 0);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
+ error("C_Login failed: %lu", rv);
+ return (-1);
+ }
+ si->logged_in = 1;
+ return (0);
+}
+
+static int
+pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
+ CK_ATTRIBUTE_TYPE type, int *val)
+{
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_BBOOL flag = 0;
+ CK_ATTRIBUTE attr;
+ CK_RV rv;
+
+ *val = 0;
+
+ if (!k11->provider || !k11->provider->valid) {
+ error("no pkcs11 (valid) provider found");
+ return (-1);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ attr.type = type;
+ attr.pValue = &flag;
+ attr.ulValueLen = sizeof(flag);
- if ((k11 = RSA_get_app_data(rsa)) == NULL) {
- error("RSA_get_app_data failed for rsa %p", rsa);
+ rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
return (-1);
}
+ *val = flag != 0;
+ debug("%s: provider %p slot %lu object %lu: attrib %lu = %d",
+ __func__, k11->provider, k11->slotidx, obj, type, *val);
+ return (0);
+}
+
+static int
+pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
+{
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_OBJECT_HANDLE obj;
+ CK_RV rv;
+ CK_OBJECT_CLASS private_key_class;
+ CK_BBOOL true_val;
+ CK_MECHANISM mech;
+ CK_ATTRIBUTE key_filter[3];
+ int always_auth = 0;
+ int did_login = 0;
+
if (!k11->provider || !k11->provider->valid) {
- error("no pkcs11 (valid) provider for rsa %p", rsa);
+ error("no pkcs11 (valid) provider found");
return (-1);
}
+
f = k11->provider->function_list;
si = &k11->provider->slotinfo[k11->slotidx];
+
if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
- if (!pkcs11_interactive) {
- error("need pin entry%s", (si->token.flags &
- CKF_PROTECTED_AUTHENTICATION_PATH) ?
- " on reader keypad" : "");
+ if (pkcs11_login(k11, CKU_USER) < 0) {
+ error("login failed");
return (-1);
}
- if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
- verbose("Deferring PIN entry to reader keypad.");
- else {
- snprintf(prompt, sizeof(prompt),
- "Enter PIN for '%s': ", si->token.label);
- pin = read_passphrase(prompt, RP_ALLOW_EOF);
- if (pin == NULL)
- return (-1); /* bail out */
- }
- rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
- (pin != NULL) ? strlen(pin) : 0);
- if (pin != NULL) {
- explicit_bzero(pin, strlen(pin));
- free(pin);
- }
- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
- error("C_Login failed: %lu", rv);
- return (-1);
- }
- si->logged_in = 1;
+ did_login = 1;
}
+
+ memset(&key_filter, 0, sizeof(key_filter));
+ private_key_class = CKO_PRIVATE_KEY;
+ key_filter[0].type = CKA_CLASS;
+ key_filter[0].pValue = &private_key_class;
+ key_filter[0].ulValueLen = sizeof(private_key_class);
+
+ key_filter[1].type = CKA_ID;
key_filter[1].pValue = k11->keyid;
key_filter[1].ulValueLen = k11->keyid_len;
+
+ true_val = CK_TRUE;
+ key_filter[2].type = CKA_SIGN;
+ key_filter[2].pValue = &true_val;
+ key_filter[2].ulValueLen = sizeof(true_val);
+
/* try to find object w/CKA_SIGN first, retry w/o */
if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
error("cannot find private key");
- } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
+ return (-1);
+ }
+
+ memset(&mech, 0, sizeof(mech));
+ mech.mechanism = mech_type;
+ mech.pParameter = NULL_PTR;
+ mech.ulParameterLen = 0;
+
+ if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
error("C_SignInit failed: %lu", rv);
- } else {
- /* XXX handle CKR_BUFFER_TOO_SMALL */
- tlen = RSA_size(rsa);
- rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
- if (rv == CKR_OK)
- rval = tlen;
- else
- error("C_Sign failed: %lu", rv);
+ return (-1);
+ }
+
+ pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
+ &always_auth); /* ignore errors here */
+ if (always_auth && !did_login) {
+ debug("%s: always-auth key", __func__);
+ if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
+ error("login failed for always-auth key");
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+/* openssl callback doing the actual signing operation */
+static int
+pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
+ int padding)
+{
+ struct pkcs11_key *k11;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_ULONG tlen = 0;
+ CK_RV rv;
+ int rval = -1;
+
+ if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) {
+ error("RSA_get_ex_data failed for rsa %p", rsa);
+ return (-1);
}
+
+ if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) {
+ error("pkcs11_get_key failed");
+ return (-1);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+ tlen = RSA_size(rsa);
+
+ /* XXX handle CKR_BUFFER_TOO_SMALL */
+ rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
+ if (rv == CKR_OK)
+ rval = tlen;
+ else
+ error("C_Sign failed: %lu", rv);
+
return (rval);
}
static int
pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
int padding)
{
return (-1);
}
+static int
+pkcs11_rsa_start_wrapper(void)
+{
+ if (rsa_method != NULL)
+ return (0);
+ rsa_method = RSA_meth_dup(RSA_get_default_method());
+ if (rsa_method == NULL)
+ return (-1);
+ rsa_idx = RSA_get_ex_new_index(0, "ssh-pkcs11-rsa",
+ NULL, NULL, pkcs11_k11_free);
+ if (rsa_idx == -1)
+ return (-1);
+ if (!RSA_meth_set1_name(rsa_method, "pkcs11") ||
+ !RSA_meth_set_priv_enc(rsa_method, pkcs11_rsa_private_encrypt) ||
+ !RSA_meth_set_priv_dec(rsa_method, pkcs11_rsa_private_decrypt)) {
+ error("%s: setup pkcs11 method failed", __func__);
+ return (-1);
+ }
+ return (0);
+}
+
/* redirect private key operations for rsa key to pkcs11 token */
static int
pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
CK_ATTRIBUTE *keyid_attrib, RSA *rsa)
{
struct pkcs11_key *k11;
- const RSA_METHOD *def = RSA_get_default_method();
+
+ if (pkcs11_rsa_start_wrapper() == -1)
+ return (-1);
k11 = xcalloc(1, sizeof(*k11));
k11->provider = provider;
provider->refcount++; /* provider referenced by RSA key */
k11->slotidx = slotidx;
/* identify key object on smartcard */
k11->keyid_len = keyid_attrib->ulValueLen;
if (k11->keyid_len > 0) {
k11->keyid = xmalloc(k11->keyid_len);
memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
}
- k11->rsa_method = RSA_meth_dup(def);
- if (k11->rsa_method == NULL)
- fatal("%s: RSA_meth_dup failed", __func__);
- k11->orig_finish = RSA_meth_get_finish(def);
- if (!RSA_meth_set1_name(k11->rsa_method, "pkcs11") ||
- !RSA_meth_set_priv_enc(k11->rsa_method,
- pkcs11_rsa_private_encrypt) ||
- !RSA_meth_set_priv_dec(k11->rsa_method,
- pkcs11_rsa_private_decrypt) ||
- !RSA_meth_set_finish(k11->rsa_method, pkcs11_rsa_finish))
- fatal("%s: setup pkcs11 method failed", __func__);
- RSA_set_method(rsa, k11->rsa_method);
- RSA_set_app_data(rsa, k11);
+
+ RSA_set_method(rsa, rsa_method);
+ RSA_set_ex_data(rsa, rsa_idx, k11);
+ return (0);
+}
+
+#ifdef HAVE_EC_KEY_METHOD_NEW
+/* openssl callback doing the actual signing operation */
+static ECDSA_SIG *
+ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
+ const BIGNUM *rp, EC_KEY *ec)
+{
+ struct pkcs11_key *k11;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_ULONG siglen = 0, bnlen;
+ CK_RV rv;
+ ECDSA_SIG *ret = NULL;
+ u_char *sig;
+ BIGNUM *r = NULL, *s = NULL;
+
+ if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) {
+ ossl_error("EC_KEY_get_key_method_data failed for ec");
+ return (NULL);
+ }
+
+ if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
+ error("pkcs11_get_key failed");
+ return (NULL);
+ }
+
+ f = k11->provider->function_list;
+ si = &k11->provider->slotinfo[k11->slotidx];
+
+ siglen = ECDSA_size(ec);
+ sig = xmalloc(siglen);
+
+ /* XXX handle CKR_BUFFER_TOO_SMALL */
+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen);
+ if (rv != CKR_OK) {
+ error("C_Sign failed: %lu", rv);
+ goto done;
+ }
+ if (siglen < 64 || siglen > 132 || siglen % 2) {
+ ossl_error("d2i_ECDSA_SIG failed");
+ goto done;
+ }
+ bnlen = siglen/2;
+ if ((ret = ECDSA_SIG_new()) == NULL) {
+ error("ECDSA_SIG_new failed");
+ goto done;
+ }
+ if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
+ (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
+ ossl_error("d2i_ECDSA_SIG failed");
+ ECDSA_SIG_free(ret);
+ ret = NULL;
+ goto done;
+ }
+ if (!ECDSA_SIG_set0(ret, r, s)) {
+ error("%s: ECDSA_SIG_set0 failed", __func__);
+ ECDSA_SIG_free(ret);
+ ret = NULL;
+ goto done;
+ }
+ r = s = NULL; /* now owned by ret */
+ /* success */
+ done:
+ BN_free(r);
+ BN_free(s);
+ free(sig);
+
+ return (ret);
+}
+
+static int
+pkcs11_ecdsa_start_wrapper(void)
+{
+ int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
+ unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
+
+ if (ec_key_method != NULL)
+ return (0);
+ ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa",
+ NULL, NULL, pkcs11_k11_free);
+ if (ec_key_idx == -1)
+ return (-1);
+ ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
+ if (ec_key_method == NULL)
+ return (-1);
+ EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL);
+ EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign);
+ return (0);
+}
+
+static int
+pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
+ CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec)
+{
+ struct pkcs11_key *k11;
+
+ if (pkcs11_ecdsa_start_wrapper() == -1)
+ return (-1);
+
+ k11 = xcalloc(1, sizeof(*k11));
+ k11->provider = provider;
+ provider->refcount++; /* provider referenced by ECDSA key */
+ k11->slotidx = slotidx;
+ /* identify key object on smartcard */
+ k11->keyid_len = keyid_attrib->ulValueLen;
+ k11->keyid = xmalloc(k11->keyid_len);
+ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
+
+ EC_KEY_set_method(ec, ec_key_method);
+ EC_KEY_set_ex_data(ec, ec_key_idx, k11);
+
return (0);
}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
/* remove trailing spaces */
static void
rmspace(u_char *buf, size_t len)
{
size_t i;
if (!len)
return;
for (i = len - 1; i > 0; i--)
if (i == len - 1 || buf[i] == ' ')
buf[i] = '\0';
else
break;
}
/*
* open a pkcs11 session and login if required.
* if pin == NULL we delay login until key use
*/
static int
-pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin)
+pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
+ CK_ULONG user)
{
- CK_RV rv;
+ struct pkcs11_slotinfo *si;
CK_FUNCTION_LIST *f;
+ CK_RV rv;
CK_SESSION_HANDLE session;
- int login_required;
+ int login_required, have_pinpad, ret;
+ char prompt[1024], *xpin = NULL;
f = p->function_list;
- login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED;
- if (pin && login_required && !strlen(pin)) {
+ si = &p->slotinfo[slotidx];
+
+ have_pinpad = si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
+ login_required = si->token.flags & CKF_LOGIN_REQUIRED;
+
+ /* fail early before opening session */
+ if (login_required && !have_pinpad && !pkcs11_interactive &&
+ (pin == NULL || strlen(pin) == 0)) {
error("pin required");
- return (-1);
+ return (-SSH_PKCS11_ERR_PIN_REQUIRED);
}
if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
- CKF_SERIAL_SESSION, NULL, NULL, &session))
- != CKR_OK) {
+ CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
error("C_OpenSession failed: %lu", rv);
return (-1);
}
- if (login_required && pin) {
- rv = f->C_Login(session, CKU_USER,
- (u_char *)pin, strlen(pin));
+ if (login_required) {
+ if (have_pinpad && (pin == NULL || strlen(pin) == 0)) {
+ /* defer PIN entry to the reader keypad */
+ rv = f->C_Login(session, CKU_USER, NULL_PTR, 0);
+ } else {
+ if (pkcs11_interactive) {
+ snprintf(prompt, sizeof(prompt),
+ "Enter PIN for '%s': ", si->token.label);
+ if ((xpin = read_passphrase(prompt,
+ RP_ALLOW_EOF)) == NULL) {
+ debug("%s: no pin specified",
+ __func__);
+ return (-SSH_PKCS11_ERR_PIN_REQUIRED);
+ }
+ pin = xpin;
+ }
+ rv = f->C_Login(session, CKU_USER,
+ (u_char *)pin, strlen(pin));
+ if (xpin != NULL)
+ freezero(xpin, strlen(xpin));
+ }
if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
error("C_Login failed: %lu", rv);
+ ret = (rv == CKR_PIN_LOCKED) ?
+ -SSH_PKCS11_ERR_PIN_LOCKED :
+ -SSH_PKCS11_ERR_LOGIN_FAIL;
if ((rv = f->C_CloseSession(session)) != CKR_OK)
error("C_CloseSession failed: %lu", rv);
- return (-1);
+ return (ret);
}
- p->slotinfo[slotidx].logged_in = 1;
+ si->logged_in = 1;
}
- p->slotinfo[slotidx].session = session;
- return (0);
-}
-
-/*
- * lookup public keys for token in slot identified by slotidx,
- * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
- * keysp points to an (possibly empty) array with *nkeys keys.
- */
-static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG,
- CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *)
- __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));
-
-static int
-pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
- struct sshkey ***keysp, int *nkeys)
-{
- CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
- CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
- CK_ATTRIBUTE pubkey_filter[] = {
- { CKA_CLASS, NULL, sizeof(pubkey_class) }
- };
- CK_ATTRIBUTE cert_filter[] = {
- { CKA_CLASS, NULL, sizeof(cert_class) }
- };
- CK_ATTRIBUTE pubkey_attribs[] = {
- { CKA_ID, NULL, 0 },
- { CKA_MODULUS, NULL, 0 },
- { CKA_PUBLIC_EXPONENT, NULL, 0 }
- };
- CK_ATTRIBUTE cert_attribs[] = {
- { CKA_ID, NULL, 0 },
- { CKA_SUBJECT, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- pubkey_filter[0].pValue = &pubkey_class;
- cert_filter[0].pValue = &cert_class;
-
- if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs,
- keysp, nkeys) < 0 ||
- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs,
- keysp, nkeys) < 0)
- return (-1);
+ si->session = session;
return (0);
}
static int
pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
{
int i;
for (i = 0; i < *nkeys; i++)
if (sshkey_equal(key, (*keysp)[i]))
return (1);
return (0);
}
-static int
-have_rsa_key(const RSA *rsa)
+#ifdef HAVE_EC_KEY_METHOD_NEW
+static struct sshkey *
+pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
+ CK_OBJECT_HANDLE *obj)
{
- const BIGNUM *rsa_n, *rsa_e;
-
- RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
- return rsa_n != NULL && rsa_e != NULL;
-}
+ CK_ATTRIBUTE key_attr[3];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ ASN1_OCTET_STRING *octet = NULL;
+ EC_KEY *ec = NULL;
+ EC_GROUP *group = NULL;
+ struct sshkey *key = NULL;
+ const unsigned char *attrp = NULL;
+ int i;
+ int nid;
-static int
-pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
- CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],
- struct sshkey ***keysp, int *nkeys)
-{
- struct sshkey *key;
- RSA *rsa;
- X509 *x509;
- EVP_PKEY *evp;
- int i;
- const u_char *cp;
- CK_RV rv;
- CK_OBJECT_HANDLE obj;
- CK_ULONG nfound;
- CK_SESSION_HANDLE session;
- CK_FUNCTION_LIST *f;
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_ID;
+ key_attr[1].type = CKA_EC_POINT;
+ key_attr[2].type = CKA_EC_PARAMS;
- f = p->function_list;
session = p->slotinfo[slotidx].session;
- /* setup a filter the looks for public keys */
- if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) {
- error("C_FindObjectsInit failed: %lu", rv);
- return (-1);
+ f = p->function_list;
+
+ /* figure out size of the attributes */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (NULL);
}
- while (1) {
- /* XXX 3 attributes in attribs[] */
- for (i = 0; i < 3; i++) {
- attribs[i].pValue = NULL;
- attribs[i].ulValueLen = 0;
- }
- if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK
- || nfound == 0)
- break;
- /* found a key, so figure out size of the attributes */
- if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
- != CKR_OK) {
- error("C_GetAttributeValue failed: %lu", rv);
- continue;
- }
- /*
- * Allow CKA_ID (always first attribute) to be empty, but
- * ensure that none of the others are zero length.
- * XXX assumes CKA_ID is always first.
- */
- if (attribs[1].ulValueLen == 0 ||
- attribs[2].ulValueLen == 0) {
- continue;
- }
- /* allocate buffers for attributes */
- for (i = 0; i < 3; i++) {
- if (attribs[i].ulValueLen > 0) {
- attribs[i].pValue = xmalloc(
- attribs[i].ulValueLen);
- }
- }
- /*
- * retrieve ID, modulus and public exponent of RSA key,
- * or ID, subject and value for certificates.
- */
- rsa = NULL;
- if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3))
- != CKR_OK) {
- error("C_GetAttributeValue failed: %lu", rv);
- } else if (attribs[1].type == CKA_MODULUS ) {
- if ((rsa = RSA_new()) == NULL) {
- error("RSA_new failed");
- } else {
- BIGNUM *rsa_n, *rsa_e;
-
- rsa_n = BN_bin2bn(attribs[1].pValue,
- attribs[1].ulValueLen, NULL);
- rsa_e = BN_bin2bn(attribs[2].pValue,
- attribs[2].ulValueLen, NULL);
- if (rsa_n != NULL && rsa_e != NULL) {
- if (!RSA_set0_key(rsa,
- rsa_n, rsa_e, NULL))
- fatal("%s: set key", __func__);
- rsa_n = rsa_e = NULL; /* transferred */
- }
- BN_free(rsa_n);
- BN_free(rsa_e);
- }
- } else {
- cp = attribs[2].pValue;
- if ((x509 = X509_new()) == NULL) {
- error("X509_new failed");
- } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen)
- == NULL) {
- error("d2i_X509 failed");
- } else if ((evp = X509_get_pubkey(x509)) == NULL ||
- EVP_PKEY_base_id(evp) != EVP_PKEY_RSA ||
- EVP_PKEY_get0_RSA(evp) == NULL) {
- debug("X509_get_pubkey failed or no rsa");
- } else if ((rsa = RSAPublicKey_dup(
- EVP_PKEY_get0_RSA(evp))) == NULL) {
- error("RSAPublicKey_dup");
- }
- X509_free(x509);
- }
- if (rsa && have_rsa_key(rsa) &&
- pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
- if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
- fatal("sshkey_new failed");
- key->rsa = rsa;
- key->type = KEY_RSA;
- key->flags |= SSHKEY_FLAG_EXT;
- if (pkcs11_key_included(keysp, nkeys, key)) {
- sshkey_free(key);
- } else {
- /* expand key array and add key */
- *keysp = xrecallocarray(*keysp, *nkeys,
- *nkeys + 1, sizeof(struct sshkey *));
- (*keysp)[*nkeys] = key;
- *nkeys = *nkeys + 1;
- debug("have %d keys", *nkeys);
- }
- } else if (rsa) {
- RSA_free(rsa);
- }
- for (i = 0; i < 3; i++)
- free(attribs[i].pValue);
+ /*
+ * Allow CKA_ID (always first attribute) to be empty, but
+ * ensure that none of the others are zero length.
+ * XXX assumes CKA_ID is always first.
+ */
+ if (key_attr[1].ulValueLen == 0 ||
+ key_attr[2].ulValueLen == 0) {
+ error("invalid attribute length");
+ return (NULL);
}
- if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK)
- error("C_FindObjectsFinal failed: %lu", rv);
- return (0);
-}
-/* register a new provider, fails if provider already exists */
-int
-pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
+ /* allocate buffers for attributes */
+ for (i = 0; i < 3; i++)
+ if (key_attr[i].ulValueLen > 0)
+ key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
+
+ /* retrieve ID, public point and curve parameters of EC key */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ ec = EC_KEY_new();
+ if (ec == NULL) {
+ error("EC_KEY_new failed");
+ goto fail;
+ }
+
+ attrp = key_attr[2].pValue;
+ group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
+ if (group == NULL) {
+ ossl_error("d2i_ECPKParameters failed");
+ goto fail;
+ }
+
+ if (EC_KEY_set_group(ec, group) == 0) {
+ ossl_error("EC_KEY_set_group failed");
+ goto fail;
+ }
+
+ if (key_attr[1].ulValueLen <= 2) {
+ error("CKA_EC_POINT too small");
+ goto fail;
+ }
+
+ attrp = key_attr[1].pValue;
+ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
+ if (octet == NULL) {
+ ossl_error("d2i_ASN1_OCTET_STRING failed");
+ goto fail;
+ }
+ attrp = octet->data;
+ if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) {
+ ossl_error("o2i_ECPublicKey failed");
+ goto fail;
+ }
+
+ nid = sshkey_ecdsa_key_to_nid(ec);
+ if (nid < 0) {
+ error("couldn't get curve nid");
+ goto fail;
+ }
+
+ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec))
+ goto fail;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto fail;
+ }
+
+ key->ecdsa = ec;
+ key->ecdsa_nid = nid;
+ key->type = KEY_ECDSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ ec = NULL; /* now owned by key */
+
+fail:
+ for (i = 0; i < 3; i++)
+ free(key_attr[i].pValue);
+ if (ec)
+ EC_KEY_free(ec);
+ if (group)
+ EC_GROUP_free(group);
+ if (octet)
+ ASN1_OCTET_STRING_free(octet);
+
+ return (key);
+}
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+
+static struct sshkey *
+pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
+ CK_OBJECT_HANDLE *obj)
+{
+ CK_ATTRIBUTE key_attr[3];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ RSA *rsa = NULL;
+ BIGNUM *rsa_n, *rsa_e;
+ struct sshkey *key = NULL;
+ int i;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_ID;
+ key_attr[1].type = CKA_MODULUS;
+ key_attr[2].type = CKA_PUBLIC_EXPONENT;
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ /* figure out size of the attributes */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (NULL);
+ }
+
+ /*
+ * Allow CKA_ID (always first attribute) to be empty, but
+ * ensure that none of the others are zero length.
+ * XXX assumes CKA_ID is always first.
+ */
+ if (key_attr[1].ulValueLen == 0 ||
+ key_attr[2].ulValueLen == 0) {
+ error("invalid attribute length");
+ return (NULL);
+ }
+
+ /* allocate buffers for attributes */
+ for (i = 0; i < 3; i++)
+ if (key_attr[i].ulValueLen > 0)
+ key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
+
+ /* retrieve ID, modulus and public exponent of RSA key */
+ rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ rsa = RSA_new();
+ if (rsa == NULL) {
+ error("RSA_new failed");
+ goto fail;
+ }
+
+ rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL);
+ rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL);
+ if (rsa_n == NULL || rsa_e == NULL) {
+ error("BN_bin2bn failed");
+ goto fail;
+ }
+ if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
+ fatal("%s: set key", __func__);
+ rsa_n = rsa_e = NULL; /* transferred */
+
+ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
+ goto fail;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto fail;
+ }
+
+ key->rsa = rsa;
+ key->type = KEY_RSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ rsa = NULL; /* now owned by key */
+
+fail:
+ for (i = 0; i < 3; i++)
+ free(key_attr[i].pValue);
+ RSA_free(rsa);
+
+ return (key);
+}
+
+static struct sshkey *
+pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
+ CK_OBJECT_HANDLE *obj)
+{
+ CK_ATTRIBUTE cert_attr[3];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ X509 *x509 = NULL;
+ EVP_PKEY *evp;
+ RSA *rsa = NULL;
+ EC_KEY *ec = NULL;
+ struct sshkey *key = NULL;
+ int i;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ int nid;
+#endif
+ const u_char *cp;
+
+ memset(&cert_attr, 0, sizeof(cert_attr));
+ cert_attr[0].type = CKA_ID;
+ cert_attr[1].type = CKA_SUBJECT;
+ cert_attr[2].type = CKA_VALUE;
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ /* figure out size of the attributes */
+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ return (NULL);
+ }
+
+ /*
+ * Allow CKA_ID (always first attribute) to be empty, but
+ * ensure that none of the others are zero length.
+ * XXX assumes CKA_ID is always first.
+ */
+ if (cert_attr[1].ulValueLen == 0 ||
+ cert_attr[2].ulValueLen == 0) {
+ error("invalid attribute length");
+ return (NULL);
+ }
+
+ /* allocate buffers for attributes */
+ for (i = 0; i < 3; i++)
+ if (cert_attr[i].ulValueLen > 0)
+ cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen);
+
+ /* retrieve ID, subject and value of certificate */
+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ x509 = X509_new();
+ if (x509 == NULL) {
+ error("x509_new failed");
+ goto fail;
+ }
+
+ cp = cert_attr[2].pValue;
+ if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) {
+ error("d2i_x509 failed");
+ goto fail;
+ }
+
+ evp = X509_get_pubkey(x509);
+ if (evp == NULL) {
+ error("X509_get_pubkey failed");
+ goto fail;
+ }
+
+ if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
+ if (EVP_PKEY_get0_RSA(evp) == NULL) {
+ error("invalid x509; no rsa key");
+ goto fail;
+ }
+ if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
+ error("RSAPublicKey_dup failed");
+ goto fail;
+ }
+
+ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
+ goto fail;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto fail;
+ }
+
+ key->rsa = rsa;
+ key->type = KEY_RSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ rsa = NULL; /* now owned by key */
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
+ if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
+ error("invalid x509; no ec key");
+ goto fail;
+ }
+ if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
+ error("EC_KEY_dup failed");
+ goto fail;
+ }
+
+ nid = sshkey_ecdsa_key_to_nid(ec);
+ if (nid < 0) {
+ error("couldn't get curve nid");
+ goto fail;
+ }
+
+ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
+ goto fail;
+
+ key = sshkey_new(KEY_UNSPEC);
+ if (key == NULL) {
+ error("sshkey_new failed");
+ goto fail;
+ }
+
+ key->ecdsa = ec;
+ key->ecdsa_nid = nid;
+ key->type = KEY_ECDSA;
+ key->flags |= SSHKEY_FLAG_EXT;
+ ec = NULL; /* now owned by key */
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+ } else
+ error("unknown certificate key type");
+
+fail:
+ for (i = 0; i < 3; i++)
+ free(cert_attr[i].pValue);
+ X509_free(x509);
+ RSA_free(rsa);
+ EC_KEY_free(ec);
+
+ return (key);
+}
+
+#if 0
+static int
+have_rsa_key(const RSA *rsa)
+{
+ const BIGNUM *rsa_n, *rsa_e;
+
+ RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
+ return rsa_n != NULL && rsa_e != NULL;
+}
+#endif
+
+/*
+ * lookup certificates for token in slot identified by slotidx,
+ * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
+ * keysp points to an (possibly empty) array with *nkeys keys.
+ */
+static int
+pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
+ struct sshkey ***keysp, int *nkeys)
+{
+ struct sshkey *key = NULL;
+ CK_OBJECT_CLASS key_class;
+ CK_ATTRIBUTE key_attr[1];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG n = 0;
+ int ret = -1;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ memset(&obj, 0, sizeof(obj));
+
+ key_class = CKO_CERTIFICATE;
+ key_attr[0].type = CKA_CLASS;
+ key_attr[0].pValue = &key_class;
+ key_attr[0].ulValueLen = sizeof(key_class);
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ rv = f->C_FindObjectsInit(session, key_attr, 1);
+ if (rv != CKR_OK) {
+ error("C_FindObjectsInit failed: %lu", rv);
+ goto fail;
+ }
+
+ while (1) {
+ CK_CERTIFICATE_TYPE ck_cert_type;
+
+ rv = f->C_FindObjects(session, &obj, 1, &n);
+ if (rv != CKR_OK) {
+ error("C_FindObjects failed: %lu", rv);
+ goto fail;
+ }
+ if (n == 0)
+ break;
+
+ memset(&ck_cert_type, 0, sizeof(ck_cert_type));
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_CERTIFICATE_TYPE;
+ key_attr[0].pValue = &ck_cert_type;
+ key_attr[0].ulValueLen = sizeof(ck_cert_type);
+
+ rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ switch (ck_cert_type) {
+ case CKC_X_509:
+ key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj);
+ break;
+ default:
+ /* XXX print key type? */
+ key = NULL;
+ error("skipping unsupported certificate type");
+ }
+
+ if (key == NULL) {
+ error("failed to fetch key");
+ continue;
+ }
+
+ if (pkcs11_key_included(keysp, nkeys, key)) {
+ sshkey_free(key);
+ } else {
+ /* expand key array and add key */
+ *keysp = xrecallocarray(*keysp, *nkeys,
+ *nkeys + 1, sizeof(struct sshkey *));
+ (*keysp)[*nkeys] = key;
+ *nkeys = *nkeys + 1;
+ debug("have %d keys", *nkeys);
+ }
+ }
+
+ ret = 0;
+fail:
+ rv = f->C_FindObjectsFinal(session);
+ if (rv != CKR_OK) {
+ error("C_FindObjectsFinal failed: %lu", rv);
+ ret = -1;
+ }
+
+ return (ret);
+}
+
+/*
+ * lookup public keys for token in slot identified by slotidx,
+ * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
+ * keysp points to an (possibly empty) array with *nkeys keys.
+ */
+static int
+pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
+ struct sshkey ***keysp, int *nkeys)
+{
+ struct sshkey *key = NULL;
+ CK_OBJECT_CLASS key_class;
+ CK_ATTRIBUTE key_attr[1];
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST *f = NULL;
+ CK_RV rv;
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG n = 0;
+ int ret = -1;
+
+ memset(&key_attr, 0, sizeof(key_attr));
+ memset(&obj, 0, sizeof(obj));
+
+ key_class = CKO_PUBLIC_KEY;
+ key_attr[0].type = CKA_CLASS;
+ key_attr[0].pValue = &key_class;
+ key_attr[0].ulValueLen = sizeof(key_class);
+
+ session = p->slotinfo[slotidx].session;
+ f = p->function_list;
+
+ rv = f->C_FindObjectsInit(session, key_attr, 1);
+ if (rv != CKR_OK) {
+ error("C_FindObjectsInit failed: %lu", rv);
+ goto fail;
+ }
+
+ while (1) {
+ CK_KEY_TYPE ck_key_type;
+
+ rv = f->C_FindObjects(session, &obj, 1, &n);
+ if (rv != CKR_OK) {
+ error("C_FindObjects failed: %lu", rv);
+ goto fail;
+ }
+ if (n == 0)
+ break;
+
+ memset(&ck_key_type, 0, sizeof(ck_key_type));
+ memset(&key_attr, 0, sizeof(key_attr));
+ key_attr[0].type = CKA_KEY_TYPE;
+ key_attr[0].pValue = &ck_key_type;
+ key_attr[0].ulValueLen = sizeof(ck_key_type);
+
+ rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
+ if (rv != CKR_OK) {
+ error("C_GetAttributeValue failed: %lu", rv);
+ goto fail;
+ }
+
+ switch (ck_key_type) {
+ case CKK_RSA:
+ key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
+ break;
+#ifdef HAVE_EC_KEY_METHOD_NEW
+ case CKK_ECDSA:
+ key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
+ break;
+#endif /* HAVE_EC_KEY_METHOD_NEW */
+ default:
+ /* XXX print key type? */
+ key = NULL;
+ error("skipping unsupported key type");
+ }
+
+ if (key == NULL) {
+ error("failed to fetch key");
+ continue;
+ }
+
+ if (pkcs11_key_included(keysp, nkeys, key)) {
+ sshkey_free(key);
+ } else {
+ /* expand key array and add key */
+ *keysp = xrecallocarray(*keysp, *nkeys,
+ *nkeys + 1, sizeof(struct sshkey *));
+ (*keysp)[*nkeys] = key;
+ *nkeys = *nkeys + 1;
+ debug("have %d keys", *nkeys);
+ }
+ }
+
+ ret = 0;
+fail:
+ rv = f->C_FindObjectsFinal(session);
+ if (rv != CKR_OK) {
+ error("C_FindObjectsFinal failed: %lu", rv);
+ ret = -1;
+ }
+
+ return (ret);
+}
+
+#ifdef WITH_PKCS11_KEYGEN
+#define FILL_ATTR(attr, idx, typ, val, len) \
+ { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
+
+static struct sshkey *
+pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
+ char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
+{
+ struct pkcs11_slotinfo *si;
+ char *plabel = label ? label : "";
+ int npub = 0, npriv = 0;
+ CK_RV rv;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE;
+ CK_OBJECT_HANDLE pubKey, privKey;
+ CK_ATTRIBUTE tpub[16], tpriv[16];
+ CK_MECHANISM mech = {
+ CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
+ };
+ CK_BYTE pubExponent[] = {
+ 0x01, 0x00, 0x01 /* RSA_F4 in bytes */
+ };
+ pubkey_filter[0].pValue = &pubkey_class;
+ cert_filter[0].pValue = &cert_class;
+
+ *err = 0;
+
+ FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits));
+ FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent,
+ sizeof(pubExponent));
+ FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
+
+ FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
+ &pubKey, &privKey)) != CKR_OK) {
+ error("%s: key generation failed: error 0x%lx", __func__, rv);
+ *err = rv;
+ return NULL;
+ }
+
+ return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
+}
+
+static int
+pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
+{
+ size_t i, len;
+ char ptr[3];
+
+ if (dest)
+ *dest = NULL;
+ if (rlen)
+ *rlen = 0;
+
+ if ((len = strlen(hex)) % 2)
+ return -1;
+ len /= 2;
+
+ *dest = xmalloc(len);
+
+ ptr[2] = '\0';
+ for (i = 0; i < len; i++) {
+ ptr[0] = hex[2 * i];
+ ptr[1] = hex[(2 * i) + 1];
+ if (!isxdigit(ptr[0]) || !isxdigit(ptr[1]))
+ return -1;
+ (*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16);
+ }
+
+ if (rlen)
+ *rlen = len;
+
+ return 0;
+}
+
+static struct ec_curve_info {
+ const char *name;
+ const char *oid;
+ const char *oid_encoded;
+ size_t size;
+} ec_curve_infos[] = {
+ {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
+ {"secp384r1", "1.3.132.0.34", "06052B81040022", 384},
+ {"secp521r1", "1.3.132.0.35", "06052B81040023", 521},
+ {NULL, NULL, NULL, 0},
+};
+
+static struct sshkey *
+pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
+ char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
+{
+ struct pkcs11_slotinfo *si;
+ char *plabel = label ? label : "";
+ int i;
+ size_t ecparams_size;
+ unsigned char *ecparams = NULL;
+ int npub = 0, npriv = 0;
+ CK_RV rv;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE;
+ CK_OBJECT_HANDLE pubKey, privKey;
+ CK_MECHANISM mech = {
+ CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
+ };
+ CK_ATTRIBUTE tpub[16], tpriv[16];
+
+ *err = 0;
+
+ for (i = 0; ec_curve_infos[i].name; i++) {
+ if (ec_curve_infos[i].size == bits)
+ break;
+ }
+ if (!ec_curve_infos[i].name) {
+ error("%s: invalid key size %lu", __func__, bits);
+ return NULL;
+ }
+ if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
+ &ecparams_size) == -1) {
+ error("%s: invalid oid", __func__);
+ return NULL;
+ }
+
+ FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
+ FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size);
+ FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
+
+ FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
+ FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
+ FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
+ sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
+ FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
+ &pubKey, &privKey)) != CKR_OK) {
+ error("%s: key generation failed: error 0x%lx", __func__, rv);
+ *err = rv;
+ return NULL;
+ }
+
+ return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
+}
+#endif /* WITH_PKCS11_KEYGEN */
+
+/*
+ * register a new provider, fails if provider already exists. if
+ * keyp is provided, fetch keys.
+ */
+static int
+pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
+ struct pkcs11_provider **providerp, CK_ULONG user)
{
int nkeys, need_finalize = 0;
+ int ret = -1;
struct pkcs11_provider *p = NULL;
void *handle = NULL;
CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
CK_RV rv;
CK_FUNCTION_LIST *f = NULL;
CK_TOKEN_INFO *token;
CK_ULONG i;
- *keyp = NULL;
+ if (providerp == NULL)
+ goto fail;
+ *providerp = NULL;
+
+ if (keyp != NULL)
+ *keyp = NULL;
+
if (pkcs11_provider_lookup(provider_id) != NULL) {
debug("%s: provider already registered: %s",
__func__, provider_id);
goto fail;
}
- /* open shared pkcs11-libarary */
+ /* open shared pkcs11-library */
if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
error("dlopen %s failed: %s", provider_id, dlerror());
goto fail;
}
if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {
error("dlsym(C_GetFunctionList) failed: %s", dlerror());
goto fail;
}
p = xcalloc(1, sizeof(*p));
p->name = xstrdup(provider_id);
p->handle = handle;
/* setup the pkcs11 callbacks */
if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
error("C_GetFunctionList for provider %s failed: %lu",
provider_id, rv);
goto fail;
}
p->function_list = f;
if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
error("C_Initialize for provider %s failed: %lu",
provider_id, rv);
goto fail;
}
need_finalize = 1;
if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
error("C_GetInfo for provider %s failed: %lu",
provider_id, rv);
goto fail;
}
rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID));
rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription));
debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d"
" libraryDescription <%s> libraryVersion %d.%d",
provider_id,
p->info.manufacturerID,
p->info.cryptokiVersion.major,
p->info.cryptokiVersion.minor,
p->info.libraryDescription,
p->info.libraryVersion.major,
p->info.libraryVersion.minor);
if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) {
error("C_GetSlotList failed: %lu", rv);
goto fail;
}
if (p->nslots == 0) {
- debug("%s: provider %s returned no slots", __func__,
+ error("%s: provider %s returned no slots", __func__,
provider_id);
+ ret = -SSH_PKCS11_ERR_NO_SLOTS;
goto fail;
}
p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
!= CKR_OK) {
error("C_GetSlotList for provider %s failed: %lu",
provider_id, rv);
goto fail;
}
p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
p->valid = 1;
nkeys = 0;
for (i = 0; i < p->nslots; i++) {
token = &p->slotinfo[i].token;
if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
!= CKR_OK) {
error("C_GetTokenInfo for provider %s slot %lu "
"failed: %lu", provider_id, (unsigned long)i, rv);
continue;
}
if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
debug2("%s: ignoring uninitialised token in "
"provider %s slot %lu", __func__,
provider_id, (unsigned long)i);
continue;
}
rmspace(token->label, sizeof(token->label));
rmspace(token->manufacturerID, sizeof(token->manufacturerID));
rmspace(token->model, sizeof(token->model));
rmspace(token->serialNumber, sizeof(token->serialNumber));
debug("provider %s slot %lu: label <%s> manufacturerID <%s> "
"model <%s> serial <%s> flags 0x%lx",
provider_id, (unsigned long)i,
token->label, token->manufacturerID, token->model,
token->serialNumber, token->flags);
- /* open session, login with pin and retrieve public keys */
- if (pkcs11_open_session(p, i, pin) == 0)
+ /*
+ * open session, login with pin and retrieve public
+ * keys (if keyp is provided)
+ */
+ if ((ret = pkcs11_open_session(p, i, pin, user)) == 0) {
+ if (keyp == NULL)
+ continue;
pkcs11_fetch_keys(p, i, keyp, &nkeys);
+ pkcs11_fetch_certs(p, i, keyp, &nkeys);
+ }
}
- if (nkeys > 0) {
- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
- p->refcount++; /* add to provider list */
- return (nkeys);
- }
- debug("%s: provider %s returned no keys", __func__, provider_id);
- /* don't add the provider, since it does not have any keys */
+
+ /* now owned by caller */
+ *providerp = p;
+
+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
+ p->refcount++; /* add to provider list */
+
+ return (nkeys);
fail:
if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
error("C_Finalize for provider %s failed: %lu",
provider_id, rv);
if (p) {
+ free(p->name);
free(p->slotlist);
free(p->slotinfo);
free(p);
}
if (handle)
dlclose(handle);
- return (-1);
+ return (ret);
+}
+
+/*
+ * register a new provider and get number of keys hold by the token,
+ * fails if provider already exists
+ */
+int
+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
+{
+ struct pkcs11_provider *p = NULL;
+ int nkeys;
+
+ nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER);
+
+ /* no keys found or some other error, de-register provider */
+ if (nkeys <= 0 && p != NULL) {
+ TAILQ_REMOVE(&pkcs11_providers, p, next);
+ pkcs11_provider_finalize(p);
+ pkcs11_provider_unref(p);
+ }
+ if (nkeys == 0)
+ debug("%s: provider %s returned no keys", __func__,
+ provider_id);
+
+ return (nkeys);
+}
+
+#ifdef WITH_PKCS11_KEYGEN
+struct sshkey *
+pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
+ unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err)
+{
+ struct pkcs11_provider *p = NULL;
+ struct pkcs11_slotinfo *si;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ struct sshkey *k = NULL;
+ int ret = -1, reset_pin = 0, reset_provider = 0;
+ CK_RV rv;
+
+ *err = 0;
+
+ if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
+ debug("%s: provider \"%s\" available", __func__, provider_id);
+ else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p,
+ CKU_SO)) < 0) {
+ debug("%s: could not register provider %s", __func__,
+ provider_id);
+ goto out;
+ } else
+ reset_provider = 1;
+
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
+ CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
+ debug("%s: could not supply SO pin: %lu", __func__, rv);
+ reset_pin = 0;
+ } else
+ reset_pin = 1;
+
+ switch (type) {
+ case KEY_RSA:
+ if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
+ bits, keyid, err)) == NULL) {
+ debug("%s: failed to generate RSA key", __func__);
+ goto out;
+ }
+ break;
+ case KEY_ECDSA:
+ if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
+ bits, keyid, err)) == NULL) {
+ debug("%s: failed to generate ECDSA key", __func__);
+ goto out;
+ }
+ break;
+ default:
+ *err = SSH_PKCS11_ERR_GENERIC;
+ debug("%s: unknown type %d", __func__, type);
+ goto out;
+ }
+
+out:
+ if (reset_pin)
+ f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
+ CK_INVALID_HANDLE);
+
+ if (reset_provider)
+ pkcs11_del_provider(provider_id);
+
+ return (k);
}
-#else
+struct sshkey *
+pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
+ unsigned char keyid, u_int32_t *err)
+{
+ struct pkcs11_provider *p = NULL;
+ struct pkcs11_slotinfo *si;
+ struct sshkey *k = NULL;
+ int reset_pin = 0, reset_provider = 0;
+ CK_ULONG nattrs;
+ CK_FUNCTION_LIST *f;
+ CK_SESSION_HANDLE session;
+ CK_ATTRIBUTE attrs[16];
+ CK_OBJECT_CLASS key_class;
+ CK_KEY_TYPE key_type;
+ CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE;
+ CK_RV rv;
+
+ *err = 0;
+
+ if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
+ debug("%s: using provider \"%s\"", __func__, provider_id);
+ } else if (pkcs11_register_provider(provider_id, pin, NULL, &p,
+ CKU_SO) < 0) {
+ debug("%s: could not register provider %s", __func__,
+ provider_id);
+ goto out;
+ } else
+ reset_provider = 1;
+ f = p->function_list;
+ si = &p->slotinfo[slotidx];
+ session = si->session;
+
+ if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
+ CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
+ debug("%s: could not supply SO pin: %lu", __func__, rv);
+ reset_pin = 0;
+ } else
+ reset_pin = 1;
+
+ /* private key */
+ nattrs = 0;
+ key_class = CKO_PRIVATE_KEY;
+ FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
+ FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
+
+ if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
+ obj != CK_INVALID_HANDLE) {
+ if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
+ debug("%s: could not destroy private key 0x%hhx",
+ __func__, keyid);
+ *err = rv;
+ goto out;
+ }
+ }
+
+ /* public key */
+ nattrs = 0;
+ key_class = CKO_PUBLIC_KEY;
+ FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
+ FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
+
+ if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
+ obj != CK_INVALID_HANDLE) {
+
+ /* get key type */
+ nattrs = 0;
+ FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
+ sizeof(key_type));
+ rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
+ if (rv != CKR_OK) {
+ debug("%s: could not get key type of public key 0x%hhx",
+ __func__, keyid);
+ *err = rv;
+ key_type = -1;
+ }
+ if (key_type == CKK_RSA)
+ k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
+ else if (key_type == CKK_ECDSA)
+ k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
+
+ if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
+ debug("%s: could not destroy public key 0x%hhx",
+ __func__, keyid);
+ *err = rv;
+ goto out;
+ }
+ }
+
+out:
+ if (reset_pin)
+ f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
+ CK_INVALID_HANDLE);
+
+ if (reset_provider)
+ pkcs11_del_provider(provider_id);
+
+ return (k);
+}
+#endif /* WITH_PKCS11_KEYGEN */
+#else /* ENABLE_PKCS11 */
int
pkcs11_init(int interactive)
{
- return (0);
+ error("%s: dlopen() not supported", __func__);
+ return (-1);
+}
+
+int
+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
+{
+ error("%s: dlopen() not supported", __func__);
+ return (-1);
}
void
pkcs11_terminate(void)
{
- return;
+ error("%s: dlopen() not supported", __func__);
}
-
#endif /* ENABLE_PKCS11 */
diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h
index 0ced74f29ce7..b9038450da8c 100644
--- a/ssh-pkcs11.h
+++ b/ssh-pkcs11.h
@@ -1,24 +1,40 @@
-/* $OpenBSD: ssh-pkcs11.h,v 1.4 2015/01/15 09:40:00 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11.h,v 1.5 2019/01/20 22:51:37 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+
+/* Errors for pkcs11_add_provider() */
+#define SSH_PKCS11_ERR_GENERIC 1
+#define SSH_PKCS11_ERR_LOGIN_FAIL 2
+#define SSH_PKCS11_ERR_NO_SLOTS 3
+#define SSH_PKCS11_ERR_PIN_REQUIRED 4
+#define SSH_PKCS11_ERR_PIN_LOCKED 5
+
int pkcs11_init(int);
void pkcs11_terminate(void);
int pkcs11_add_provider(char *, char *, struct sshkey ***);
int pkcs11_del_provider(char *);
+#ifdef WITH_PKCS11_KEYGEN
+struct sshkey *
+ pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int,
+ unsigned int, unsigned char, u_int32_t *);
+struct sshkey *
+ pkcs11_destroy_keypair(char *, char *, unsigned long, unsigned char,
+ u_int32_t *);
+#endif
#if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11)
#undef ENABLE_PKCS11
#endif
diff --git a/ssh.0 b/ssh.0
index 2d8994ffc759..f53bda666149 100644
--- a/ssh.0
+++ b/ssh.0
@@ -1,982 +1,980 @@
SSH(1) General Commands Manual SSH(1)
NAME
ssh M-bM-^@M-^S OpenSSH SSH client (remote login program)
SYNOPSIS
ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]
[-c cipher_spec] [-D [bind_address:]port] [-E log_file]
[-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]
[-J destination] [-L address] [-l login_name] [-m mac_spec]
[-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]
[-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]] destination
[command]
DESCRIPTION
ssh (SSH client) is a program for logging into a remote machine and for
executing commands on a remote machine. It is intended to provide secure
encrypted communications between two untrusted hosts over an insecure
network. X11 connections, arbitrary TCP ports and UNIX-domain sockets
can also be forwarded over the secure channel.
ssh connects and logs into the specified destination, which may be
specified as either [user@]hostname or a URI of the form
ssh://[user@]hostname[:port]. The user must prove his/her identity to
the remote machine using one of several methods (see below).
If a command is specified, it is executed on the remote host instead of a
login shell.
The options are as follows:
-4 Forces ssh to use IPv4 addresses only.
-6 Forces ssh to use IPv6 addresses only.
-A Enables forwarding of the authentication agent connection. This
can also be specified on a per-host basis in a configuration
file.
Agent forwarding should be enabled with caution. Users with the
ability to bypass file permissions on the remote host (for the
agent's UNIX-domain socket) can access the local agent through
the forwarded connection. An attacker cannot obtain key material
from the agent, however they can perform operations on the keys
that enable them to authenticate using the identities loaded into
the agent.
-a Disables forwarding of the authentication agent connection.
-B bind_interface
Bind to the address of bind_interface before attempting to
connect to the destination host. This is only useful on systems
with more than one address.
-b bind_address
Use bind_address on the local machine as the source address of
the connection. Only useful on systems with more than one
address.
-C Requests compression of all data (including stdin, stdout,
stderr, and data for forwarded X11, TCP and UNIX-domain
connections). The compression algorithm is the same used by
gzip(1). Compression is desirable on modem lines and other slow
connections, but will only slow down things on fast networks.
The default value can be set on a host-by-host basis in the
configuration files; see the Compression option.
-c cipher_spec
Selects the cipher specification for encrypting the session.
cipher_spec is a comma-separated list of ciphers listed in order
of preference. See the Ciphers keyword in ssh_config(5) for more
information.
-D [bind_address:]port
Specifies a local M-bM-^@M-^\dynamicM-bM-^@M-^] application-level port forwarding.
This works by allocating a socket to listen to port on the local
side, optionally bound to the specified bind_address. Whenever a
connection is made to this port, the connection is forwarded over
the secure channel, and the application protocol is then used to
determine where to connect to from the remote machine. Currently
the SOCKS4 and SOCKS5 protocols are supported, and ssh will act
as a SOCKS server. Only root can forward privileged ports.
Dynamic port forwardings can also be specified in the
configuration file.
IPv6 addresses can be specified by enclosing the address in
square brackets. Only the superuser can forward privileged
ports. By default, the local port is bound in accordance with
the GatewayPorts setting. However, an explicit bind_address may
be used to bind the connection to a specific address. The
bind_address of M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be
bound for local use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates
that the port should be available from all interfaces.
-E log_file
Append debug logs to log_file instead of standard error.
-e escape_char
Sets the escape character for sessions with a pty (default: M-bM-^@M-^X~M-bM-^@M-^Y).
The escape character is only recognized at the beginning of a
line. The escape character followed by a dot (M-bM-^@M-^X.M-bM-^@M-^Y) closes the
connection; followed by control-Z suspends the connection; and
followed by itself sends the escape character once. Setting the
character to M-bM-^@M-^\noneM-bM-^@M-^] disables any escapes and makes the session
fully transparent.
-F configfile
Specifies an alternative per-user configuration file. If a
configuration file is given on the command line, the system-wide
configuration file (/etc/ssh/ssh_config) will be ignored. The
default for the per-user configuration file is ~/.ssh/config.
-f Requests ssh to go to background just before command execution.
This is useful if ssh is going to ask for passwords or
passphrases, but the user wants it in the background. This
implies -n. The recommended way to start X11 programs at a
remote site is with something like ssh -f host xterm.
If the ExitOnForwardFailure configuration option is set to M-bM-^@M-^\yesM-bM-^@M-^],
then a client started with -f will wait for all remote port
forwards to be successfully established before placing itself in
the background.
-G Causes ssh to print its configuration after evaluating Host and
Match blocks and exit.
-g Allows remote hosts to connect to local forwarded ports. If used
on a multiplexed connection, then this option must be specified
on the master process.
-I pkcs11
Specify the PKCS#11 shared library ssh should use to communicate
- with a PKCS#11 token providing the user's private RSA key.
+ with a PKCS#11 token providing keys for user authentication.
-i identity_file
Selects a file from which the identity (private key) for public
key authentication is read. The default is ~/.ssh/id_dsa,
~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_rsa. Identity
files may also be specified on a per-host basis in the
configuration file. It is possible to have multiple -i options
(and multiple identities specified in configuration files). If
no certificates have been explicitly specified by the
CertificateFile directive, ssh will also try to load certificate
information from the filename obtained by appending -cert.pub to
identity filenames.
-J destination
Connect to the target host by first making a ssh connection to
the jump host described by destination and then establishing a
TCP forwarding to the ultimate destination from there. Multiple
jump hops may be specified separated by comma characters. This
is a shortcut to specify a ProxyJump configuration directive.
+ Note that configuration directives supplied on the command-line
+ generally apply to the destination host and not any specified
+ jump hosts. Use ~/.ssh/config to specify configuration for jump
+ hosts.
-K Enables GSSAPI-based authentication and forwarding (delegation)
of GSSAPI credentials to the server.
-k Disables forwarding (delegation) of GSSAPI credentials to the
server.
-L [bind_address:]port:host:hostport
-L [bind_address:]port:remote_socket
-L local_socket:host:hostport
-L local_socket:remote_socket
Specifies that connections to the given TCP port or Unix socket
on the local (client) host are to be forwarded to the given host
and port, or Unix socket, on the remote side. This works by
allocating a socket to listen to either a TCP port on the local
side, optionally bound to the specified bind_address, or to a
Unix socket. Whenever a connection is made to the local port or
socket, the connection is forwarded over the secure channel, and
a connection is made to either host port hostport, or the Unix
socket remote_socket, from the remote machine.
Port forwardings can also be specified in the configuration file.
Only the superuser can forward privileged ports. IPv6 addresses
can be specified by enclosing the address in square brackets.
By default, the local port is bound in accordance with the
GatewayPorts setting. However, an explicit bind_address may be
used to bind the connection to a specific address. The
bind_address of M-bM-^@M-^\localhostM-bM-^@M-^] indicates that the listening port be
bound for local use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates
that the port should be available from all interfaces.
-l login_name
Specifies the user to log in as on the remote machine. This also
may be specified on a per-host basis in the configuration file.
-M Places the ssh client into M-bM-^@M-^\masterM-bM-^@M-^] mode for connection sharing.
Multiple -M options places ssh into M-bM-^@M-^\masterM-bM-^@M-^] mode but with
confirmation required using ssh-askpass(1) before each operation
that changes the multiplexing state (e.g. opening a new session).
Refer to the description of ControlMaster in ssh_config(5) for
details.
-m mac_spec
A comma-separated list of MAC (message authentication code)
algorithms, specified in order of preference. See the MACs
keyword for more information.
-N Do not execute a remote command. This is useful for just
forwarding ports.
-n Redirects stdin from /dev/null (actually, prevents reading from
stdin). This must be used when ssh is run in the background. A
common trick is to use this to run X11 programs on a remote
machine. For example, ssh -n shadows.cs.hut.fi emacs & will
start an emacs on shadows.cs.hut.fi, and the X11 connection will
be automatically forwarded over an encrypted channel. The ssh
program will be put in the background. (This does not work if
ssh needs to ask for a password or passphrase; see also the -f
option.)
-O ctl_cmd
Control an active connection multiplexing master process. When
the -O option is specified, the ctl_cmd argument is interpreted
and passed to the master process. Valid commands are: M-bM-^@M-^\checkM-bM-^@M-^]
(check that the master process is running), M-bM-^@M-^\forwardM-bM-^@M-^] (request
forwardings without command execution), M-bM-^@M-^\cancelM-bM-^@M-^] (cancel
forwardings), M-bM-^@M-^\exitM-bM-^@M-^] (request the master to exit), and M-bM-^@M-^\stopM-bM-^@M-^]
(request the master to stop accepting further multiplexing
requests).
-o option
Can be used to give options in the format used in the
configuration file. This is useful for specifying options for
which there is no separate command-line flag. For full details
of the options listed below, and their possible values, see
ssh_config(5).
AddKeysToAgent
AddressFamily
BatchMode
BindAddress
CanonicalDomains
CanonicalizeFallbackLocal
CanonicalizeHostname
CanonicalizeMaxDots
CanonicalizePermittedCNAMEs
CASignatureAlgorithms
CertificateFile
ChallengeResponseAuthentication
CheckHostIP
Ciphers
ClearAllForwardings
Compression
ConnectionAttempts
ConnectTimeout
ControlMaster
ControlPath
ControlPersist
DynamicForward
EscapeChar
ExitOnForwardFailure
FingerprintHash
ForwardAgent
ForwardX11
ForwardX11Timeout
ForwardX11Trusted
GatewayPorts
GlobalKnownHostsFile
GSSAPIAuthentication
GSSAPIDelegateCredentials
HashKnownHosts
Host
HostbasedAuthentication
HostbasedKeyTypes
HostKeyAlgorithms
HostKeyAlias
HostName
IdentitiesOnly
IdentityAgent
IdentityFile
IPQoS
KbdInteractiveAuthentication
KbdInteractiveDevices
KexAlgorithms
LocalCommand
LocalForward
LogLevel
MACs
Match
NoHostAuthenticationForLocalhost
NumberOfPasswordPrompts
PasswordAuthentication
PermitLocalCommand
PKCS11Provider
Port
PreferredAuthentications
ProxyCommand
ProxyJump
ProxyUseFdpass
PubkeyAcceptedKeyTypes
PubkeyAuthentication
RekeyLimit
RemoteCommand
RemoteForward
RequestTTY
SendEnv
ServerAliveInterval
ServerAliveCountMax
SetEnv
StreamLocalBindMask
StreamLocalBindUnlink
StrictHostKeyChecking
TCPKeepAlive
Tunnel
TunnelDevice
UpdateHostKeys
User
UserKnownHostsFile
VerifyHostKeyDNS
VisualHostKey
XAuthLocation
-p port
Port to connect to on the remote host. This can be specified on
a per-host basis in the configuration file.
-Q query_option
Queries ssh for the algorithms supported for the specified
version 2. The available features are: cipher (supported
symmetric ciphers), cipher-auth (supported symmetric ciphers that
support authenticated encryption), help (supported query terms
for use with the -Q flag), mac (supported message integrity
codes), kex (key exchange algorithms), key (key types), key-cert
(certificate key types), key-plain (non-certificate key types),
protocol-version (supported SSH protocol versions), and sig
(supported signature algorithms).
-q Quiet mode. Causes most warning and diagnostic messages to be
suppressed.
-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket
-R [bind_address:]port
Specifies that connections to the given TCP port or Unix socket
on the remote (server) host are to be forwarded to the local
side.
This works by allocating a socket to listen to either a TCP port
or to a Unix socket on the remote side. Whenever a connection is
made to this port or Unix socket, the connection is forwarded
over the secure channel, and a connection is made from the local
machine to either an explicit destination specified by host port
hostport, or local_socket, or, if no explicit destination was
specified, ssh will act as a SOCKS 4/5 proxy and forward
connections to the destinations requested by the remote SOCKS
client.
Port forwardings can also be specified in the configuration file.
Privileged ports can be forwarded only when logging in as root on
the remote machine. IPv6 addresses can be specified by enclosing
the address in square brackets.
By default, TCP listening sockets on the server will be bound to
the loopback interface only. This may be overridden by
specifying a bind_address. An empty bind_address, or the address
M-bM-^@M-^X*M-bM-^@M-^Y, indicates that the remote socket should listen on all
interfaces. Specifying a remote bind_address will only succeed
if the server's GatewayPorts option is enabled (see
sshd_config(5)).
If the port argument is M-bM-^@M-^X0M-bM-^@M-^Y, the listen port will be dynamically
allocated on the server and reported to the client at run time.
When used together with -O forward the allocated port will be
printed to the standard output.
-S ctl_path
Specifies the location of a control socket for connection
sharing, or the string M-bM-^@M-^\noneM-bM-^@M-^] to disable connection sharing.
Refer to the description of ControlPath and ControlMaster in
ssh_config(5) for details.
-s May be used to request invocation of a subsystem on the remote
system. Subsystems facilitate the use of SSH as a secure
transport for other applications (e.g. sftp(1)). The subsystem
is specified as the remote command.
-T Disable pseudo-terminal allocation.
-t Force pseudo-terminal allocation. This can be used to execute
arbitrary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
-V Display the version number and exit.
-v Verbose mode. Causes ssh to print debugging messages about its
progress. This is helpful in debugging connection,
authentication, and configuration problems. Multiple -v options
increase the verbosity. The maximum is 3.
-W host:port
Requests that standard input and output on the client be
forwarded to host on port over the secure channel. Implies -N,
-T, ExitOnForwardFailure and ClearAllForwardings, though these
can be overridden in the configuration file or using -o command
line options.
-w local_tun[:remote_tun]
Requests tunnel device forwarding with the specified tun(4)
devices between the client (local_tun) and the server
(remote_tun).
The devices may be specified by numerical ID or the keyword
M-bM-^@M-^\anyM-bM-^@M-^], which uses the next available tunnel device. If
remote_tun is not specified, it defaults to M-bM-^@M-^\anyM-bM-^@M-^]. See also the
Tunnel and TunnelDevice directives in ssh_config(5).
If the Tunnel directive is unset, it will be set to the default
tunnel mode, which is M-bM-^@M-^\point-to-pointM-bM-^@M-^]. If a different Tunnel
forwarding mode it desired, then it should be specified before
-w.
-X Enables X11 forwarding. This can also be specified on a per-host
basis in a configuration file.
X11 forwarding should be enabled with caution. Users with the
ability to bypass file permissions on the remote host (for the
user's X authorization database) can access the local X11 display
through the forwarded connection. An attacker may then be able
to perform activities such as keystroke monitoring.
For this reason, X11 forwarding is subjected to X11 SECURITY
extension restrictions by default. Please refer to the ssh -Y
option and the ForwardX11Trusted directive in ssh_config(5) for
more information.
-x Disables X11 forwarding.
-Y Enables trusted X11 forwarding. Trusted X11 forwardings are not
subjected to the X11 SECURITY extension controls.
-y Send log information using the syslog(3) system module. By
default this information is sent to stderr.
ssh may additionally obtain configuration data from a per-user
configuration file and a system-wide configuration file. The file format
and configuration options are described in ssh_config(5).
AUTHENTICATION
The OpenSSH SSH client supports SSH protocol 2.
The methods available for authentication are: GSSAPI-based
authentication, host-based authentication, public key authentication,
challenge-response authentication, and password authentication.
Authentication methods are tried in the order specified above, though
PreferredAuthentications can be used to change the default order.
Host-based authentication works as follows: If the machine the user logs
in from is listed in /etc/hosts.equiv or /etc/shosts.equiv on the remote
machine, and the user names are the same on both sides, or if the files
~/.rhosts or ~/.shosts exist in the user's home directory on the remote
machine and contain a line containing the name of the client machine and
the name of the user on that machine, the user is considered for login.
Additionally, the server must be able to verify the client's host key
(see the description of /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts,
below) for login to be permitted. This authentication method closes
security holes due to IP spoofing, DNS spoofing, and routing spoofing.
[Note to the administrator: /etc/hosts.equiv, ~/.rhosts, and the
rlogin/rsh protocol in general, are inherently insecure and should be
disabled if security is desired.]
Public key authentication works as follows: The scheme is based on
public-key cryptography, using cryptosystems where encryption and
decryption are done using separate keys, and it is unfeasible to derive
the decryption key from the encryption key. The idea is that each user
creates a public/private key pair for authentication purposes. The
server knows the public key, and only the user knows the private key.
ssh implements public key authentication protocol automatically, using
one of the DSA, ECDSA, Ed25519 or RSA algorithms. The HISTORY section of
ssl(8) contains a brief discussion of the DSA and RSA algorithms.
The file ~/.ssh/authorized_keys lists the public keys that are permitted
for logging in. When the user logs in, the ssh program tells the server
which key pair it would like to use for authentication. The client
proves that it has access to the private key and the server checks that
the corresponding public key is authorized to accept the account.
The server may inform the client of errors that prevented public key
authentication from succeeding after authentication completes using a
different method. These may be viewed by increasing the LogLevel to
DEBUG or higher (e.g. by using the -v flag).
The user creates his/her key pair by running ssh-keygen(1). This stores
the private key in ~/.ssh/id_dsa (DSA), ~/.ssh/id_ecdsa (ECDSA),
~/.ssh/id_ed25519 (Ed25519), or ~/.ssh/id_rsa (RSA) and stores the public
key in ~/.ssh/id_dsa.pub (DSA), ~/.ssh/id_ecdsa.pub (ECDSA),
~/.ssh/id_ed25519.pub (Ed25519), or ~/.ssh/id_rsa.pub (RSA) in the user's
home directory. The user should then copy the public key to
~/.ssh/authorized_keys in his/her home directory on the remote machine.
The authorized_keys file corresponds to the conventional ~/.rhosts file,
and has one key per line, though the lines can be very long. After this,
the user can log in without giving the password.
A variation on public key authentication is available in the form of
certificate authentication: instead of a set of public/private keys,
signed certificates are used. This has the advantage that a single
trusted certification authority can be used in place of many
public/private keys. See the CERTIFICATES section of ssh-keygen(1) for
more information.
The most convenient way to use public key or certificate authentication
may be with an authentication agent. See ssh-agent(1) and (optionally)
the AddKeysToAgent directive in ssh_config(5) for more information.
Challenge-response authentication works as follows: The server sends an
arbitrary "challenge" text, and prompts for a response. Examples of
challenge-response authentication include BSD Authentication (see
login.conf(5)) and PAM (some non-OpenBSD systems).
Finally, if other authentication methods fail, ssh prompts the user for a
password. The password is sent to the remote host for checking; however,
since all communications are encrypted, the password cannot be seen by
someone listening on the network.
ssh automatically maintains and checks a database containing
identification for all hosts it has ever been used with. Host keys are
stored in ~/.ssh/known_hosts in the user's home directory. Additionally,
the file /etc/ssh/ssh_known_hosts is automatically checked for known
hosts. Any new hosts are automatically added to the user's file. If a
host's identification ever changes, ssh warns about this and disables
password authentication to prevent server spoofing or man-in-the-middle
attacks, which could otherwise be used to circumvent the encryption. The
StrictHostKeyChecking option can be used to control logins to machines
whose host key is not known or has changed.
When the user's identity has been accepted by the server, the server
either executes the given command in a non-interactive session or, if no
command has been specified, logs into the machine and gives the user a
normal shell as an interactive session. All communication with the
remote command or shell will be automatically encrypted.
If an interactive session is requested ssh by default will only request a
pseudo-terminal (pty) for interactive sessions when the client has one.
The flags -T and -t can be used to override this behaviour.
If a pseudo-terminal has been allocated the user may use the escape
characters noted below.
If no pseudo-terminal has been allocated, the session is transparent and
can be used to reliably transfer binary data. On most systems, setting
the escape character to M-bM-^@M-^\noneM-bM-^@M-^] will also make the session transparent
even if a tty is used.
The session terminates when the command or shell on the remote machine
exits and all X11 and TCP connections have been closed.
ESCAPE CHARACTERS
When a pseudo-terminal has been requested, ssh supports a number of
functions through the use of an escape character.
A single tilde character can be sent as ~~ or by following the tilde by a
character other than those described below. The escape character must
always follow a newline to be interpreted as special. The escape
character can be changed in configuration files using the EscapeChar
configuration directive or on the command line by the -e option.
The supported escapes (assuming the default M-bM-^@M-^X~M-bM-^@M-^Y) are:
~. Disconnect.
~^Z Background ssh.
~# List forwarded connections.
~& Background ssh at logout when waiting for forwarded connection /
X11 sessions to terminate.
~? Display a list of escape characters.
~B Send a BREAK to the remote system (only useful if the peer
supports it).
~C Open command line. Currently this allows the addition of port
forwardings using the -L, -R and -D options (see above). It also
allows the cancellation of existing port-forwardings with
-KL[bind_address:]port for local, -KR[bind_address:]port for
remote and -KD[bind_address:]port for dynamic port-forwardings.
!command allows the user to execute a local command if the
PermitLocalCommand option is enabled in ssh_config(5). Basic
help is available, using the -h option.
~R Request rekeying of the connection (only useful if the peer
supports it).
~V Decrease the verbosity (LogLevel) when errors are being written
to stderr.
~v Increase the verbosity (LogLevel) when errors are being written
to stderr.
TCP FORWARDING
- Forwarding of arbitrary TCP connections over the secure channel can be
+ Forwarding of arbitrary TCP connections over a secure channel can be
specified either on the command line or in a configuration file. One
possible application of TCP forwarding is a secure connection to a mail
server; another is going through firewalls.
- In the example below, we look at encrypting communication between an IRC
- client and server, even though the IRC server does not directly support
- encrypted communications. This works as follows: the user connects to
- the remote host using ssh, specifying a port to be used to forward
- connections to the remote server. After that it is possible to start the
- service which is to be encrypted on the client machine, connecting to the
- same local port, and ssh will encrypt and forward the connection.
+ In the example below, we look at encrypting communication for an IRC
+ client, even though the IRC server it connects to does not directly
+ support encrypted communication. This works as follows: the user
+ connects to the remote host using ssh, specifying the ports to be used to
+ forward the connection. After that it is possible to start the program
+ locally, and ssh will encrypt and forward the connection to the remote
+ server.
- The following example tunnels an IRC session from client machine
- M-bM-^@M-^\127.0.0.1M-bM-^@M-^] (localhost) to remote server M-bM-^@M-^\server.example.comM-bM-^@M-^]:
+ The following example tunnels an IRC session from the client to an IRC
+ server at M-bM-^@M-^\server.example.comM-bM-^@M-^], joining channel M-bM-^@M-^\#usersM-bM-^@M-^], nickname
+ M-bM-^@M-^\pinkyM-bM-^@M-^], using the standard IRC port, 6667:
- $ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
- $ irc -c '#users' -p 1234 pinky 127.0.0.1
-
- This tunnels a connection to IRC server M-bM-^@M-^\server.example.comM-bM-^@M-^], joining
- channel M-bM-^@M-^\#usersM-bM-^@M-^], nickname M-bM-^@M-^\pinkyM-bM-^@M-^], using port 1234. It doesn't matter
- which port is used, as long as it's greater than 1023 (remember, only
- root can open sockets on privileged ports) and doesn't conflict with any
- ports already in use. The connection is forwarded to port 6667 on the
- remote server, since that's the standard port for IRC services.
+ $ ssh -f -L 6667:localhost:6667 server.example.com sleep 10
+ $ irc -c '#users' pinky IRC/127.0.0.1
The -f option backgrounds ssh and the remote command M-bM-^@M-^\sleep 10M-bM-^@M-^] is
specified to allow an amount of time (10 seconds, in the example) to
- start the service which is to be tunnelled. If no connections are made
- within the time specified, ssh will exit.
+ start the program which is going to use the tunnel. If no connections
+ are made within the time specified, ssh will exit.
X11 FORWARDING
If the ForwardX11 variable is set to M-bM-^@M-^\yesM-bM-^@M-^] (or see the description of the
-X, -x, and -Y options above) and the user is using X11 (the DISPLAY
environment variable is set), the connection to the X11 display is
automatically forwarded to the remote side in such a way that any X11
programs started from the shell (or command) will go through the
encrypted channel, and the connection to the real X server will be made
from the local machine. The user should not manually set DISPLAY.
Forwarding of X11 connections can be configured on the command line or in
configuration files.
The DISPLAY value set by ssh will point to the server machine, but with a
display number greater than zero. This is normal, and happens because
ssh creates a M-bM-^@M-^\proxyM-bM-^@M-^] X server on the server machine for forwarding the
connections over the encrypted channel.
ssh will also automatically set up Xauthority data on the server machine.
For this purpose, it will generate a random authorization cookie, store
it in Xauthority on the server, and verify that any forwarded connections
carry this cookie and replace it by the real cookie when the connection
is opened. The real authentication cookie is never sent to the server
machine (and no cookies are sent in the plain).
If the ForwardAgent variable is set to M-bM-^@M-^\yesM-bM-^@M-^] (or see the description of
the -A and -a options above) and the user is using an authentication
agent, the connection to the agent is automatically forwarded to the
remote side.
VERIFYING HOST KEYS
When connecting to a server for the first time, a fingerprint of the
server's public key is presented to the user (unless the option
StrictHostKeyChecking has been disabled). Fingerprints can be determined
using ssh-keygen(1):
$ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
If the fingerprint is already known, it can be matched and the key can be
accepted or rejected. If only legacy (MD5) fingerprints for the server
are available, the ssh-keygen(1) -E option may be used to downgrade the
fingerprint algorithm to match.
Because of the difficulty of comparing host keys just by looking at
fingerprint strings, there is also support to compare host keys visually,
using random art. By setting the VisualHostKey option to M-bM-^@M-^\yesM-bM-^@M-^], a small
ASCII graphic gets displayed on every login to a server, no matter if the
session itself is interactive or not. By learning the pattern a known
server produces, a user can easily find out that the host key has changed
when a completely different pattern is displayed. Because these patterns
are not unambiguous however, a pattern that looks similar to the pattern
remembered only gives a good probability that the host key is the same,
not guaranteed proof.
To get a listing of the fingerprints along with their random art for all
known hosts, the following command line can be used:
$ ssh-keygen -lv -f ~/.ssh/known_hosts
If the fingerprint is unknown, an alternative method of verification is
available: SSH fingerprints verified by DNS. An additional resource
record (RR), SSHFP, is added to a zonefile and the connecting client is
able to match the fingerprint with that of the key presented.
In this example, we are connecting a client to a server,
M-bM-^@M-^\host.example.comM-bM-^@M-^]. The SSHFP resource records should first be added to
the zonefile for host.example.com:
$ ssh-keygen -r host.example.com.
The output lines will have to be added to the zonefile. To check that
the zone is answering fingerprint queries:
$ dig -t SSHFP host.example.com
Finally the client connects:
$ ssh -o "VerifyHostKeyDNS ask" host.example.com
[...]
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
See the VerifyHostKeyDNS option in ssh_config(5) for more information.
SSH-BASED VIRTUAL PRIVATE NETWORKS
ssh contains support for Virtual Private Network (VPN) tunnelling using
the tun(4) network pseudo-device, allowing two networks to be joined
securely. The sshd_config(5) configuration option PermitTunnel controls
whether the server supports this, and at what level (layer 2 or 3
traffic).
The following example would connect client network 10.0.50.0/24 with
remote network 10.0.99.0/24 using a point-to-point connection from
10.1.1.1 to 10.1.1.2, provided that the SSH server running on the gateway
to the remote network, at 192.168.1.15, allows it.
On the client:
# ssh -f -w 0:1 192.168.1.15 true
# ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
# route add 10.0.99.0/24 10.1.1.2
On the server:
# ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
# route add 10.0.50.0/24 10.1.1.1
Client access may be more finely tuned via the /root/.ssh/authorized_keys
file (see below) and the PermitRootLogin server option. The following
entry would permit connections on tun(4) device 1 from user M-bM-^@M-^\janeM-bM-^@M-^] and on
tun device 2 from user M-bM-^@M-^\johnM-bM-^@M-^], if PermitRootLogin is set to
M-bM-^@M-^\forced-commands-onlyM-bM-^@M-^]:
tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
Since an SSH-based setup entails a fair amount of overhead, it may be
more suited to temporary setups, such as for wireless VPNs. More
permanent VPNs are better provided by tools such as ipsecctl(8) and
isakmpd(8).
ENVIRONMENT
ssh will normally set the following environment variables:
DISPLAY The DISPLAY variable indicates the location of the
X11 server. It is automatically set by ssh to
point to a value of the form M-bM-^@M-^\hostname:nM-bM-^@M-^], where
M-bM-^@M-^\hostnameM-bM-^@M-^] indicates the host where the shell runs,
and M-bM-^@M-^XnM-bM-^@M-^Y is an integer M-bM-^IM-% 1. ssh uses this special
value to forward X11 connections over the secure
channel. The user should normally not set DISPLAY
explicitly, as that will render the X11 connection
insecure (and will require the user to manually
copy any required authorization cookies).
HOME Set to the path of the user's home directory.
LOGNAME Synonym for USER; set for compatibility with
systems that use this variable.
MAIL Set to the path of the user's mailbox.
PATH Set to the default PATH, as specified when
compiling ssh.
SSH_ASKPASS If ssh needs a passphrase, it will read the
passphrase from the current terminal if it was run
from a terminal. If ssh does not have a terminal
associated with it but DISPLAY and SSH_ASKPASS are
set, it will execute the program specified by
SSH_ASKPASS and open an X11 window to read the
passphrase. This is particularly useful when
calling ssh from a .xsession or related script.
(Note that on some machines it may be necessary to
redirect the input from /dev/null to make this
work.)
SSH_AUTH_SOCK Identifies the path of a UNIX-domain socket used to
communicate with the agent.
SSH_CONNECTION Identifies the client and server ends of the
connection. The variable contains four space-
separated values: client IP address, client port
number, server IP address, and server port number.
SSH_ORIGINAL_COMMAND This variable contains the original command line if
a forced command is executed. It can be used to
extract the original arguments.
SSH_TTY This is set to the name of the tty (path to the
device) associated with the current shell or
command. If the current session has no tty, this
variable is not set.
SSH_TUNNEL Optionally set by sshd(8) to contain the interface
names assigned if tunnel forwarding was requested
by the client.
SSH_USER_AUTH Optionally set by sshd(8), this variable may
contain a pathname to a file that lists the
authentication methods successfully used when the
session was established, including any public keys
that were used.
TZ This variable is set to indicate the present time
zone if it was set when the daemon was started
(i.e. the daemon passes the value on to new
connections).
USER Set to the name of the user logging in.
Additionally, ssh reads ~/.ssh/environment, and adds lines of the format
M-bM-^@M-^\VARNAME=valueM-bM-^@M-^] to the environment if the file exists and users are
allowed to change their environment. For more information, see the
PermitUserEnvironment option in sshd_config(5).
FILES
~/.rhosts
This file is used for host-based authentication (see above). On
some machines this file may need to be world-readable if the
user's home directory is on an NFS partition, because sshd(8)
reads it as root. Additionally, this file must be owned by the
user, and must not have write permissions for anyone else. The
recommended permission for most machines is read/write for the
user, and not accessible by others.
~/.shosts
This file is used in exactly the same way as .rhosts, but allows
host-based authentication without permitting login with
rlogin/rsh.
~/.ssh/
This directory is the default location for all user-specific
configuration and authentication information. There is no
general requirement to keep the entire contents of this directory
secret, but the recommended permissions are read/write/execute
for the user, and not accessible by others.
~/.ssh/authorized_keys
Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used
for logging in as this user. The format of this file is
described in the sshd(8) manual page. This file is not highly
sensitive, but the recommended permissions are read/write for the
user, and not accessible by others.
~/.ssh/config
This is the per-user configuration file. The file format and
configuration options are described in ssh_config(5). Because of
the potential for abuse, this file must have strict permissions:
read/write for the user, and not writable by others.
~/.ssh/environment
Contains additional definitions for environment variables; see
ENVIRONMENT, above.
~/.ssh/id_dsa
~/.ssh/id_ecdsa
~/.ssh/id_ed25519
~/.ssh/id_rsa
Contains the private key for authentication. These files contain
sensitive data and should be readable by the user but not
accessible by others (read/write/execute). ssh will simply
ignore a private key file if it is accessible by others. It is
possible to specify a passphrase when generating the key which
will be used to encrypt the sensitive part of this file using
AES-128.
~/.ssh/id_dsa.pub
~/.ssh/id_ecdsa.pub
~/.ssh/id_ed25519.pub
~/.ssh/id_rsa.pub
Contains the public key for authentication. These files are not
sensitive and can (but need not) be readable by anyone.
~/.ssh/known_hosts
Contains a list of host keys for all hosts the user has logged
into that are not already in the systemwide list of known host
keys. See sshd(8) for further details of the format of this
file.
~/.ssh/rc
Commands in this file are executed by ssh when the user logs in,
just before the user's shell (or command) is started. See the
sshd(8) manual page for more information.
/etc/hosts.equiv
This file is for host-based authentication (see above). It
should only be writable by root.
/etc/shosts.equiv
This file is used in exactly the same way as hosts.equiv, but
allows host-based authentication without permitting login with
rlogin/rsh.
/etc/ssh/ssh_config
Systemwide configuration file. The file format and configuration
options are described in ssh_config(5).
/etc/ssh/ssh_host_key
/etc/ssh/ssh_host_dsa_key
/etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_rsa_key
These files contain the private parts of the host keys and are
used for host-based authentication.
/etc/ssh/ssh_known_hosts
Systemwide list of known host keys. This file should be prepared
by the system administrator to contain the public host keys of
all machines in the organization. It should be world-readable.
See sshd(8) for further details of the format of this file.
/etc/ssh/sshrc
Commands in this file are executed by ssh when the user logs in,
just before the user's shell (or command) is started. See the
sshd(8) manual page for more information.
EXIT STATUS
ssh exits with the exit status of the remote command or with 255 if an
error occurred.
SEE ALSO
scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1),
tun(4), ssh_config(5), ssh-keysign(8), sshd(8)
STANDARDS
S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned
Numbers, RFC 4250, January 2006.
T. Ylonen and C. Lonvick, The Secure Shell (SSH) Protocol Architecture,
RFC 4251, January 2006.
T. Ylonen and C. Lonvick, The Secure Shell (SSH) Authentication Protocol,
RFC 4252, January 2006.
T. Ylonen and C. Lonvick, The Secure Shell (SSH) Transport Layer
Protocol, RFC 4253, January 2006.
T. Ylonen and C. Lonvick, The Secure Shell (SSH) Connection Protocol, RFC
4254, January 2006.
J. Schlyter and W. Griffin, Using DNS to Securely Publish Secure Shell
(SSH) Key Fingerprints, RFC 4255, January 2006.
F. Cusack and M. Forssen, Generic Message Exchange Authentication for the
Secure Shell Protocol (SSH), RFC 4256, January 2006.
J. Galbraith and P. Remaker, The Secure Shell (SSH) Session Channel Break
Extension, RFC 4335, January 2006.
M. Bellare, T. Kohno, and C. Namprempre, The Secure Shell (SSH) Transport
Layer Encryption Modes, RFC 4344, January 2006.
B. Harris, Improved Arcfour Modes for the Secure Shell (SSH) Transport
Layer Protocol, RFC 4345, January 2006.
M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for
the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006.
J. Galbraith and R. Thayer, The Secure Shell (SSH) Public Key File
Format, RFC 4716, November 2006.
D. Stebila and J. Green, Elliptic Curve Algorithm Integration in the
Secure Shell Transport Layer, RFC 5656, December 2009.
A. Perrig and D. Song, Hash Visualization: a New Technique to improve
Real-World Security, 1999, International Workshop on Cryptographic
Techniques and E-Commerce (CrypTEC '99).
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
-OpenBSD 6.4 September 20, 2018 OpenBSD 6.4
+OpenBSD 6.5 March 16, 2019 OpenBSD 6.5
diff --git a/ssh.1 b/ssh.1
index 7760c307596f..9480eba8d3ec 100644
--- a/ssh.1
+++ b/ssh.1
@@ -1,1709 +1,1700 @@
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" As far as I am concerned, the code I have written for this software
.\" can be used freely for any purpose. Any derived versions of this
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh.1,v 1.399 2018/09/20 06:58:48 jmc Exp $
-.Dd $Mdocdate: September 20 2018 $
+.\" $OpenBSD: ssh.1,v 1.402 2019/03/16 19:14:21 jmc Exp $
+.Dd $Mdocdate: March 16 2019 $
.Dt SSH 1
.Os
.Sh NAME
.Nm ssh
.Nd OpenSSH SSH client (remote login program)
.Sh SYNOPSIS
.Nm ssh
.Op Fl 46AaCfGgKkMNnqsTtVvXxYy
.Op Fl B Ar bind_interface
.Op Fl b Ar bind_address
.Op Fl c Ar cipher_spec
.Op Fl D Oo Ar bind_address : Oc Ns Ar port
.Op Fl E Ar log_file
.Op Fl e Ar escape_char
.Op Fl F Ar configfile
.Op Fl I Ar pkcs11
.Op Fl i Ar identity_file
.Op Fl J Ar destination
.Op Fl L Ar address
.Op Fl l Ar login_name
.Op Fl m Ar mac_spec
.Op Fl O Ar ctl_cmd
.Op Fl o Ar option
.Op Fl p Ar port
.Op Fl Q Ar query_option
.Op Fl R Ar address
.Op Fl S Ar ctl_path
.Op Fl W Ar host : Ns Ar port
.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
.Ar destination
.Op Ar command
.Sh DESCRIPTION
.Nm
(SSH client) is a program for logging into a remote machine and for
executing commands on a remote machine.
It is intended to provide secure encrypted communications between
two untrusted hosts over an insecure network.
X11 connections, arbitrary TCP ports and
.Ux Ns -domain
sockets can also be forwarded over the secure channel.
.Pp
.Nm
connects and logs into the specified
.Ar destination ,
which may be specified as either
.Sm off
.Oo user @ Oc hostname
.Sm on
or a URI of the form
.Sm off
.No ssh:// Oo user @ Oc hostname Op : port .
.Sm on
The user must prove
his/her identity to the remote machine using one of several methods
(see below).
.Pp
If a
.Ar command
is specified,
it is executed on the remote host instead of a login shell.
.Pp
The options are as follows:
.Pp
.Bl -tag -width Ds -compact
.It Fl 4
Forces
.Nm
to use IPv4 addresses only.
.Pp
.It Fl 6
Forces
.Nm
to use IPv6 addresses only.
.Pp
.It Fl A
Enables forwarding of the authentication agent connection.
This can also be specified on a per-host basis in a configuration file.
.Pp
Agent forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host
(for the agent's
.Ux Ns -domain
socket) can access the local agent through the forwarded connection.
An attacker cannot obtain key material from the agent,
however they can perform operations on the keys that enable them to
authenticate using the identities loaded into the agent.
.Pp
.It Fl a
Disables forwarding of the authentication agent connection.
.Pp
.It Fl B Ar bind_interface
Bind to the address of
.Ar bind_interface
before attempting to connect to the destination host.
This is only useful on systems with more than one address.
.Pp
.It Fl b Ar bind_address
Use
.Ar bind_address
on the local machine as the source address
of the connection.
Only useful on systems with more than one address.
.Pp
.It Fl C
Requests compression of all data (including stdin, stdout, stderr, and
data for forwarded X11, TCP and
.Ux Ns -domain
connections).
The compression algorithm is the same used by
.Xr gzip 1 .
Compression is desirable on modem lines and other
slow connections, but will only slow down things on fast networks.
The default value can be set on a host-by-host basis in the
configuration files; see the
.Cm Compression
option.
.Pp
.It Fl c Ar cipher_spec
Selects the cipher specification for encrypting the session.
.Ar cipher_spec
is a comma-separated list of ciphers
listed in order of preference.
See the
.Cm Ciphers
keyword in
.Xr ssh_config 5
for more information.
.Pp
.It Fl D Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port
.Sm on
.Xc
Specifies a local
.Dq dynamic
application-level port forwarding.
This works by allocating a socket to listen to
.Ar port
on the local side, optionally bound to the specified
.Ar bind_address .
Whenever a connection is made to this port, the
connection is forwarded over the secure channel, and the application
protocol is then used to determine where to connect to from the
remote machine.
Currently the SOCKS4 and SOCKS5 protocols are supported, and
.Nm
will act as a SOCKS server.
Only root can forward privileged ports.
Dynamic port forwardings can also be specified in the configuration file.
.Pp
IPv6 addresses can be specified by enclosing the address in square brackets.
Only the superuser can forward privileged ports.
By default, the local port is bound in accordance with the
.Cm GatewayPorts
setting.
However, an explicit
.Ar bind_address
may be used to bind the connection to a specific address.
The
.Ar bind_address
of
.Dq localhost
indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
.Pp
.It Fl E Ar log_file
Append debug logs to
.Ar log_file
instead of standard error.
.Pp
.It Fl e Ar escape_char
Sets the escape character for sessions with a pty (default:
.Ql ~ ) .
The escape character is only recognized at the beginning of a line.
The escape character followed by a dot
.Pq Ql \&.
closes the connection;
followed by control-Z suspends the connection;
and followed by itself sends the escape character once.
Setting the character to
.Dq none
disables any escapes and makes the session fully transparent.
.Pp
.It Fl F Ar configfile
Specifies an alternative per-user configuration file.
If a configuration file is given on the command line,
the system-wide configuration file
.Pq Pa /etc/ssh/ssh_config
will be ignored.
The default for the per-user configuration file is
.Pa ~/.ssh/config .
.Pp
.It Fl f
Requests
.Nm
to go to background just before command execution.
This is useful if
.Nm
is going to ask for passwords or passphrases, but the user
wants it in the background.
This implies
.Fl n .
The recommended way to start X11 programs at a remote site is with
something like
.Ic ssh -f host xterm .
.Pp
If the
.Cm ExitOnForwardFailure
configuration option is set to
.Dq yes ,
then a client started with
.Fl f
will wait for all remote port forwards to be successfully established
before placing itself in the background.
.Pp
.It Fl G
Causes
.Nm
to print its configuration after evaluating
.Cm Host
and
.Cm Match
blocks and exit.
.Pp
.It Fl g
Allows remote hosts to connect to local forwarded ports.
If used on a multiplexed connection, then this option must be specified
on the master process.
.Pp
.It Fl I Ar pkcs11
Specify the PKCS#11 shared library
.Nm
-should use to communicate with a PKCS#11 token providing the user's
-private RSA key.
+should use to communicate with a PKCS#11 token providing keys for user
+authentication.
.Pp
.It Fl i Ar identity_file
Selects a file from which the identity (private key) for
public key authentication is read.
The default is
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
.Pa ~/.ssh/id_ed25519
and
.Pa ~/.ssh/id_rsa .
Identity files may also be specified on
a per-host basis in the configuration file.
It is possible to have multiple
.Fl i
options (and multiple identities specified in
configuration files).
If no certificates have been explicitly specified by the
.Cm CertificateFile
directive,
.Nm
will also try to load certificate information from the filename obtained
by appending
.Pa -cert.pub
to identity filenames.
.Pp
.It Fl J Ar destination
Connect to the target host by first making a
.Nm
connection to the jump host described by
.Ar destination
and then establishing a TCP forwarding to the ultimate destination from
there.
Multiple jump hops may be specified separated by comma characters.
This is a shortcut to specify a
.Cm ProxyJump
configuration directive.
+Note that configuration directives supplied on the command-line generally
+apply to the destination host and not any specified jump hosts.
+Use
+.Pa ~/.ssh/config
+to specify configuration for jump hosts.
.Pp
.It Fl K
Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI
credentials to the server.
.Pp
.It Fl k
Disables forwarding (delegation) of GSSAPI credentials to the server.
.Pp
.It Fl L Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port : host : hostport
.Sm on
.Xc
.It Fl L Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port : remote_socket
.Sm on
.Xc
.It Fl L Xo
.Sm off
.Ar local_socket : host : hostport
.Sm on
.Xc
.It Fl L Xo
.Sm off
.Ar local_socket : remote_socket
.Sm on
.Xc
Specifies that connections to the given TCP port or Unix socket on the local
(client) host are to be forwarded to the given host and port, or Unix socket,
on the remote side.
This works by allocating a socket to listen to either a TCP
.Ar port
on the local side, optionally bound to the specified
.Ar bind_address ,
or to a Unix socket.
Whenever a connection is made to the local port or socket, the
connection is forwarded over the secure channel, and a connection is
made to either
.Ar host
port
.Ar hostport ,
or the Unix socket
.Ar remote_socket ,
from the remote machine.
.Pp
Port forwardings can also be specified in the configuration file.
Only the superuser can forward privileged ports.
IPv6 addresses can be specified by enclosing the address in square brackets.
.Pp
By default, the local port is bound in accordance with the
.Cm GatewayPorts
setting.
However, an explicit
.Ar bind_address
may be used to bind the connection to a specific address.
The
.Ar bind_address
of
.Dq localhost
indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
.Pp
.It Fl l Ar login_name
Specifies the user to log in as on the remote machine.
This also may be specified on a per-host basis in the configuration file.
.Pp
.It Fl M
Places the
.Nm
client into
.Dq master
mode for connection sharing.
Multiple
.Fl M
options places
.Nm
into
.Dq master
mode but with confirmation required using
.Xr ssh-askpass 1
before each operation that changes the multiplexing state
(e.g. opening a new session).
Refer to the description of
.Cm ControlMaster
in
.Xr ssh_config 5
for details.
.Pp
.It Fl m Ar mac_spec
A comma-separated list of MAC (message authentication code) algorithms,
specified in order of preference.
See the
.Cm MACs
keyword for more information.
.Pp
.It Fl N
Do not execute a remote command.
This is useful for just forwarding ports.
.Pp
.It Fl n
Redirects stdin from
.Pa /dev/null
(actually, prevents reading from stdin).
This must be used when
.Nm
is run in the background.
A common trick is to use this to run X11 programs on a remote machine.
For example,
.Ic ssh -n shadows.cs.hut.fi emacs &
will start an emacs on shadows.cs.hut.fi, and the X11
connection will be automatically forwarded over an encrypted channel.
The
.Nm
program will be put in the background.
(This does not work if
.Nm
needs to ask for a password or passphrase; see also the
.Fl f
option.)
.Pp
.It Fl O Ar ctl_cmd
Control an active connection multiplexing master process.
When the
.Fl O
option is specified, the
.Ar ctl_cmd
argument is interpreted and passed to the master process.
Valid commands are:
.Dq check
(check that the master process is running),
.Dq forward
(request forwardings without command execution),
.Dq cancel
(cancel forwardings),
.Dq exit
(request the master to exit), and
.Dq stop
(request the master to stop accepting further multiplexing requests).
.Pp
.It Fl o Ar option
Can be used to give options in the format used in the configuration file.
This is useful for specifying options for which there is no separate
command-line flag.
For full details of the options listed below, and their possible values, see
.Xr ssh_config 5 .
.Pp
.Bl -tag -width Ds -offset indent -compact
.It AddKeysToAgent
.It AddressFamily
.It BatchMode
.It BindAddress
.It CanonicalDomains
.It CanonicalizeFallbackLocal
.It CanonicalizeHostname
.It CanonicalizeMaxDots
.It CanonicalizePermittedCNAMEs
.It CASignatureAlgorithms
.It CertificateFile
.It ChallengeResponseAuthentication
.It CheckHostIP
.It Ciphers
.It ClearAllForwardings
.It Compression
.It ConnectionAttempts
.It ConnectTimeout
.It ControlMaster
.It ControlPath
.It ControlPersist
.It DynamicForward
.It EscapeChar
.It ExitOnForwardFailure
.It FingerprintHash
.It ForwardAgent
.It ForwardX11
.It ForwardX11Timeout
.It ForwardX11Trusted
.It GatewayPorts
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
.It HostbasedAuthentication
.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
.It HostName
.It IdentitiesOnly
.It IdentityAgent
.It IdentityFile
.It IPQoS
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
.It KexAlgorithms
.It LocalCommand
.It LocalForward
.It LogLevel
.It MACs
.It Match
.It NoHostAuthenticationForLocalhost
.It NumberOfPasswordPrompts
.It PasswordAuthentication
.It PermitLocalCommand
.It PKCS11Provider
.It Port
.It PreferredAuthentications
.It ProxyCommand
.It ProxyJump
.It ProxyUseFdpass
.It PubkeyAcceptedKeyTypes
.It PubkeyAuthentication
.It RekeyLimit
.It RemoteCommand
.It RemoteForward
.It RequestTTY
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
.It SetEnv
.It StreamLocalBindMask
.It StreamLocalBindUnlink
.It StrictHostKeyChecking
.It TCPKeepAlive
.It Tunnel
.It TunnelDevice
.It UpdateHostKeys
.It User
.It UserKnownHostsFile
.It VerifyHostKeyDNS
.It VisualHostKey
.It XAuthLocation
.El
.Pp
.It Fl p Ar port
Port to connect to on the remote host.
This can be specified on a
per-host basis in the configuration file.
.Pp
.It Fl Q Ar query_option
Queries
.Nm
for the algorithms supported for the specified version 2.
The available features are:
.Ar cipher
(supported symmetric ciphers),
.Ar cipher-auth
(supported symmetric ciphers that support authenticated encryption),
.Ar help
(supported query terms for use with the
.Fl Q
flag),
.Ar mac
(supported message integrity codes),
.Ar kex
(key exchange algorithms),
.Ar key
(key types),
.Ar key-cert
(certificate key types),
.Ar key-plain
(non-certificate key types),
.Ar protocol-version
(supported SSH protocol versions), and
.Ar sig
(supported signature algorithms).
.Pp
.It Fl q
Quiet mode.
Causes most warning and diagnostic messages to be suppressed.
.Pp
.It Fl R Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port : host : hostport
.Sm on
.Xc
.It Fl R Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port : local_socket
.Sm on
.Xc
.It Fl R Xo
.Sm off
.Ar remote_socket : host : hostport
.Sm on
.Xc
.It Fl R Xo
.Sm off
.Ar remote_socket : local_socket
.Sm on
.Xc
.It Fl R Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port
.Sm on
.Xc
Specifies that connections to the given TCP port or Unix socket on the remote
(server) host are to be forwarded to the local side.
.Pp
This works by allocating a socket to listen to either a TCP
.Ar port
or to a Unix socket on the remote side.
Whenever a connection is made to this port or Unix socket, the
connection is forwarded over the secure channel, and a connection
is made from the local machine to either an explicit destination specified by
.Ar host
port
.Ar hostport ,
or
.Ar local_socket ,
or, if no explicit destination was specified,
.Nm
will act as a SOCKS 4/5 proxy and forward connections to the destinations
requested by the remote SOCKS client.
.Pp
Port forwardings can also be specified in the configuration file.
Privileged ports can be forwarded only when
logging in as root on the remote machine.
IPv6 addresses can be specified by enclosing the address in square brackets.
.Pp
By default, TCP listening sockets on the server will be bound to the loopback
interface only.
This may be overridden by specifying a
.Ar bind_address .
An empty
.Ar bind_address ,
or the address
.Ql * ,
indicates that the remote socket should listen on all interfaces.
Specifying a remote
.Ar bind_address
will only succeed if the server's
.Cm GatewayPorts
option is enabled (see
.Xr sshd_config 5 ) .
.Pp
If the
.Ar port
argument is
.Ql 0 ,
the listen port will be dynamically allocated on the server and reported
to the client at run time.
When used together with
.Ic -O forward
the allocated port will be printed to the standard output.
.Pp
.It Fl S Ar ctl_path
Specifies the location of a control socket for connection sharing,
or the string
.Dq none
to disable connection sharing.
Refer to the description of
.Cm ControlPath
and
.Cm ControlMaster
in
.Xr ssh_config 5
for details.
.Pp
.It Fl s
May be used to request invocation of a subsystem on the remote system.
Subsystems facilitate the use of SSH
as a secure transport for other applications (e.g.\&
.Xr sftp 1 ) .
The subsystem is specified as the remote command.
.Pp
.It Fl T
Disable pseudo-terminal allocation.
.Pp
.It Fl t
Force pseudo-terminal allocation.
This can be used to execute arbitrary
screen-based programs on a remote machine, which can be very useful,
e.g. when implementing menu services.
Multiple
.Fl t
options force tty allocation, even if
.Nm
has no local tty.
.Pp
.It Fl V
Display the version number and exit.
.Pp
.It Fl v
Verbose mode.
Causes
.Nm
to print debugging messages about its progress.
This is helpful in
debugging connection, authentication, and configuration problems.
Multiple
.Fl v
options increase the verbosity.
The maximum is 3.
.Pp
.It Fl W Ar host : Ns Ar port
Requests that standard input and output on the client be forwarded to
.Ar host
on
.Ar port
over the secure channel.
Implies
.Fl N ,
.Fl T ,
.Cm ExitOnForwardFailure
and
.Cm ClearAllForwardings ,
though these can be overridden in the configuration file or using
.Fl o
command line options.
.Pp
.It Fl w Xo
.Ar local_tun Ns Op : Ns Ar remote_tun
.Xc
Requests
tunnel
device forwarding with the specified
.Xr tun 4
devices between the client
.Pq Ar local_tun
and the server
.Pq Ar remote_tun .
.Pp
The devices may be specified by numerical ID or the keyword
.Dq any ,
which uses the next available tunnel device.
If
.Ar remote_tun
is not specified, it defaults to
.Dq any .
See also the
.Cm Tunnel
and
.Cm TunnelDevice
directives in
.Xr ssh_config 5 .
.Pp
If the
.Cm Tunnel
directive is unset, it will be set to the default tunnel mode, which is
.Dq point-to-point .
If a different
.Cm Tunnel
forwarding mode it desired, then it should be specified before
.Fl w .
.Pp
.It Fl X
Enables X11 forwarding.
This can also be specified on a per-host basis in a configuration file.
.Pp
X11 forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host
(for the user's X authorization database)
can access the local X11 display through the forwarded connection.
An attacker may then be able to perform activities such as keystroke monitoring.
.Pp
For this reason, X11 forwarding is subjected to X11 SECURITY extension
restrictions by default.
Please refer to the
.Nm
.Fl Y
option and the
.Cm ForwardX11Trusted
directive in
.Xr ssh_config 5
for more information.
.Pp
.It Fl x
Disables X11 forwarding.
.Pp
.It Fl Y
Enables trusted X11 forwarding.
Trusted X11 forwardings are not subjected to the X11 SECURITY extension
controls.
.Pp
.It Fl y
Send log information using the
.Xr syslog 3
system module.
By default this information is sent to stderr.
.El
.Pp
.Nm
may additionally obtain configuration data from
a per-user configuration file and a system-wide configuration file.
The file format and configuration options are described in
.Xr ssh_config 5 .
.Sh AUTHENTICATION
The OpenSSH SSH client supports SSH protocol 2.
.Pp
The methods available for authentication are:
GSSAPI-based authentication,
host-based authentication,
public key authentication,
challenge-response authentication,
and password authentication.
Authentication methods are tried in the order specified above,
though
.Cm PreferredAuthentications
can be used to change the default order.
.Pp
Host-based authentication works as follows:
If the machine the user logs in from is listed in
.Pa /etc/hosts.equiv
or
.Pa /etc/shosts.equiv
on the remote machine, and the user names are
the same on both sides, or if the files
.Pa ~/.rhosts
or
.Pa ~/.shosts
exist in the user's home directory on the
remote machine and contain a line containing the name of the client
machine and the name of the user on that machine, the user is
considered for login.
Additionally, the server
.Em must
be able to verify the client's
host key (see the description of
.Pa /etc/ssh/ssh_known_hosts
and
.Pa ~/.ssh/known_hosts ,
below)
for login to be permitted.
This authentication method closes security holes due to IP
spoofing, DNS spoofing, and routing spoofing.
[Note to the administrator:
.Pa /etc/hosts.equiv ,
.Pa ~/.rhosts ,
and the rlogin/rsh protocol in general, are inherently insecure and should be
disabled if security is desired.]
.Pp
Public key authentication works as follows:
The scheme is based on public-key cryptography,
using cryptosystems
where encryption and decryption are done using separate keys,
and it is unfeasible to derive the decryption key from the encryption key.
The idea is that each user creates a public/private
key pair for authentication purposes.
The server knows the public key, and only the user knows the private key.
.Nm
implements public key authentication protocol automatically,
using one of the DSA, ECDSA, Ed25519 or RSA algorithms.
The HISTORY section of
.Xr ssl 8
contains a brief discussion of the DSA and RSA algorithms.
.Pp
The file
.Pa ~/.ssh/authorized_keys
lists the public keys that are permitted for logging in.
When the user logs in, the
.Nm
program tells the server which key pair it would like to use for
authentication.
The client proves that it has access to the private key
and the server checks that the corresponding public key
is authorized to accept the account.
.Pp
The server may inform the client of errors that prevented public key
authentication from succeeding after authentication completes using a
different method.
These may be viewed by increasing the
.Cm LogLevel
to
.Cm DEBUG
or higher (e.g. by using the
.Fl v
flag).
.Pp
The user creates his/her key pair by running
.Xr ssh-keygen 1 .
This stores the private key in
.Pa ~/.ssh/id_dsa
(DSA),
.Pa ~/.ssh/id_ecdsa
(ECDSA),
.Pa ~/.ssh/id_ed25519
(Ed25519),
or
.Pa ~/.ssh/id_rsa
(RSA)
and stores the public key in
.Pa ~/.ssh/id_dsa.pub
(DSA),
.Pa ~/.ssh/id_ecdsa.pub
(ECDSA),
.Pa ~/.ssh/id_ed25519.pub
(Ed25519),
or
.Pa ~/.ssh/id_rsa.pub
(RSA)
in the user's home directory.
The user should then copy the public key
to
.Pa ~/.ssh/authorized_keys
in his/her home directory on the remote machine.
The
.Pa authorized_keys
file corresponds to the conventional
.Pa ~/.rhosts
file, and has one key
per line, though the lines can be very long.
After this, the user can log in without giving the password.
.Pp
A variation on public key authentication
is available in the form of certificate authentication:
instead of a set of public/private keys,
signed certificates are used.
This has the advantage that a single trusted certification authority
can be used in place of many public/private keys.
See the CERTIFICATES section of
.Xr ssh-keygen 1
for more information.
.Pp
The most convenient way to use public key or certificate authentication
may be with an authentication agent.
See
.Xr ssh-agent 1
and (optionally) the
.Cm AddKeysToAgent
directive in
.Xr ssh_config 5
for more information.
.Pp
Challenge-response authentication works as follows:
The server sends an arbitrary
.Qq challenge
text, and prompts for a response.
Examples of challenge-response authentication include
.Bx
Authentication (see
.Xr login.conf 5 )
and PAM (some
.Pf non- Ox
systems).
.Pp
Finally, if other authentication methods fail,
.Nm
prompts the user for a password.
The password is sent to the remote
host for checking; however, since all communications are encrypted,
the password cannot be seen by someone listening on the network.
.Pp
.Nm
automatically maintains and checks a database containing
identification for all hosts it has ever been used with.
Host keys are stored in
.Pa ~/.ssh/known_hosts
in the user's home directory.
Additionally, the file
.Pa /etc/ssh/ssh_known_hosts
is automatically checked for known hosts.
Any new hosts are automatically added to the user's file.
If a host's identification ever changes,
.Nm
warns about this and disables password authentication to prevent
server spoofing or man-in-the-middle attacks,
which could otherwise be used to circumvent the encryption.
The
.Cm StrictHostKeyChecking
option can be used to control logins to machines whose
host key is not known or has changed.
.Pp
When the user's identity has been accepted by the server, the server
either executes the given command in a non-interactive session or,
if no command has been specified, logs into the machine and gives
the user a normal shell as an interactive session.
All communication with
the remote command or shell will be automatically encrypted.
.Pp
If an interactive session is requested
.Nm
by default will only request a pseudo-terminal (pty) for interactive
sessions when the client has one.
The flags
.Fl T
and
.Fl t
can be used to override this behaviour.
.Pp
If a pseudo-terminal has been allocated the
user may use the escape characters noted below.
.Pp
If no pseudo-terminal has been allocated,
the session is transparent and can be used to reliably transfer binary data.
On most systems, setting the escape character to
.Dq none
will also make the session transparent even if a tty is used.
.Pp
The session terminates when the command or shell on the remote
machine exits and all X11 and TCP connections have been closed.
.Sh ESCAPE CHARACTERS
When a pseudo-terminal has been requested,
.Nm
supports a number of functions through the use of an escape character.
.Pp
A single tilde character can be sent as
.Ic ~~
or by following the tilde by a character other than those described below.
The escape character must always follow a newline to be interpreted as
special.
The escape character can be changed in configuration files using the
.Cm EscapeChar
configuration directive or on the command line by the
.Fl e
option.
.Pp
The supported escapes (assuming the default
.Ql ~ )
are:
.Bl -tag -width Ds
.It Cm ~.
Disconnect.
.It Cm ~^Z
Background
.Nm .
.It Cm ~#
List forwarded connections.
.It Cm ~&
Background
.Nm
at logout when waiting for forwarded connection / X11 sessions to terminate.
.It Cm ~?
Display a list of escape characters.
.It Cm ~B
Send a BREAK to the remote system
(only useful if the peer supports it).
.It Cm ~C
Open command line.
Currently this allows the addition of port forwardings using the
.Fl L ,
.Fl R
and
.Fl D
options (see above).
It also allows the cancellation of existing port-forwardings
with
.Sm off
.Fl KL Oo Ar bind_address : Oc Ar port
.Sm on
for local,
.Sm off
.Fl KR Oo Ar bind_address : Oc Ar port
.Sm on
for remote and
.Sm off
.Fl KD Oo Ar bind_address : Oc Ar port
.Sm on
for dynamic port-forwardings.
.Ic !\& Ns Ar command
allows the user to execute a local command if the
.Ic PermitLocalCommand
option is enabled in
.Xr ssh_config 5 .
Basic help is available, using the
.Fl h
option.
.It Cm ~R
Request rekeying of the connection
(only useful if the peer supports it).
.It Cm ~V
Decrease the verbosity
.Pq Ic LogLevel
when errors are being written to stderr.
.It Cm ~v
Increase the verbosity
.Pq Ic LogLevel
when errors are being written to stderr.
.El
.Sh TCP FORWARDING
-Forwarding of arbitrary TCP connections over the secure channel can
-be specified either on the command line or in a configuration file.
+Forwarding of arbitrary TCP connections over a secure channel
+can be specified either on the command line or in a configuration file.
One possible application of TCP forwarding is a secure connection to a
mail server; another is going through firewalls.
.Pp
-In the example below, we look at encrypting communication between
-an IRC client and server, even though the IRC server does not directly
-support encrypted communications.
+In the example below, we look at encrypting communication for an IRC client,
+even though the IRC server it connects to does not directly
+support encrypted communication.
This works as follows:
the user connects to the remote host using
.Nm ,
-specifying a port to be used to forward connections
-to the remote server.
-After that it is possible to start the service which is to be encrypted
-on the client machine,
-connecting to the same local port,
+specifying the ports to be used to forward the connection.
+After that it is possible to start the program locally,
and
.Nm
-will encrypt and forward the connection.
+will encrypt and forward the connection to the remote server.
.Pp
-The following example tunnels an IRC session from client machine
-.Dq 127.0.0.1
-(localhost)
-to remote server
-.Dq server.example.com :
-.Bd -literal -offset 4n
-$ ssh -f -L 1234:localhost:6667 server.example.com sleep 10
-$ irc -c '#users' -p 1234 pinky 127.0.0.1
-.Ed
-.Pp
-This tunnels a connection to IRC server
+The following example tunnels an IRC session from the client
+to an IRC server at
.Dq server.example.com ,
joining channel
.Dq #users ,
nickname
.Dq pinky ,
-using port 1234.
-It doesn't matter which port is used,
-as long as it's greater than 1023
-(remember, only root can open sockets on privileged ports)
-and doesn't conflict with any ports already in use.
-The connection is forwarded to port 6667 on the remote server,
-since that's the standard port for IRC services.
+using the standard IRC port, 6667:
+.Bd -literal -offset 4n
+$ ssh -f -L 6667:localhost:6667 server.example.com sleep 10
+$ irc -c '#users' pinky IRC/127.0.0.1
+.Ed
.Pp
The
.Fl f
option backgrounds
.Nm
and the remote command
.Dq sleep 10
is specified to allow an amount of time
(10 seconds, in the example)
-to start the service which is to be tunnelled.
+to start the program which is going to use the tunnel.
If no connections are made within the time specified,
.Nm
will exit.
.Sh X11 FORWARDING
If the
.Cm ForwardX11
variable is set to
.Dq yes
(or see the description of the
.Fl X ,
.Fl x ,
and
.Fl Y
options above)
and the user is using X11 (the
.Ev DISPLAY
environment variable is set), the connection to the X11 display is
automatically forwarded to the remote side in such a way that any X11
programs started from the shell (or command) will go through the
encrypted channel, and the connection to the real X server will be made
from the local machine.
The user should not manually set
.Ev DISPLAY .
Forwarding of X11 connections can be
configured on the command line or in configuration files.
.Pp
The
.Ev DISPLAY
value set by
.Nm
will point to the server machine, but with a display number greater than zero.
This is normal, and happens because
.Nm
creates a
.Dq proxy
X server on the server machine for forwarding the
connections over the encrypted channel.
.Pp
.Nm
will also automatically set up Xauthority data on the server machine.
For this purpose, it will generate a random authorization cookie,
store it in Xauthority on the server, and verify that any forwarded
connections carry this cookie and replace it by the real cookie when
the connection is opened.
The real authentication cookie is never
sent to the server machine (and no cookies are sent in the plain).
.Pp
If the
.Cm ForwardAgent
variable is set to
.Dq yes
(or see the description of the
.Fl A
and
.Fl a
options above) and
the user is using an authentication agent, the connection to the agent
is automatically forwarded to the remote side.
.Sh VERIFYING HOST KEYS
When connecting to a server for the first time,
a fingerprint of the server's public key is presented to the user
(unless the option
.Cm StrictHostKeyChecking
has been disabled).
Fingerprints can be determined using
.Xr ssh-keygen 1 :
.Pp
.Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key
.Pp
If the fingerprint is already known, it can be matched
and the key can be accepted or rejected.
If only legacy (MD5) fingerprints for the server are available, the
.Xr ssh-keygen 1
.Fl E
option may be used to downgrade the fingerprint algorithm to match.
.Pp
Because of the difficulty of comparing host keys
just by looking at fingerprint strings,
there is also support to compare host keys visually,
using
.Em random art .
By setting the
.Cm VisualHostKey
option to
.Dq yes ,
a small ASCII graphic gets displayed on every login to a server, no matter
if the session itself is interactive or not.
By learning the pattern a known server produces, a user can easily
find out that the host key has changed when a completely different pattern
is displayed.
Because these patterns are not unambiguous however, a pattern that looks
similar to the pattern remembered only gives a good probability that the
host key is the same, not guaranteed proof.
.Pp
To get a listing of the fingerprints along with their random art for
all known hosts, the following command line can be used:
.Pp
.Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts
.Pp
If the fingerprint is unknown,
an alternative method of verification is available:
SSH fingerprints verified by DNS.
An additional resource record (RR),
SSHFP,
is added to a zonefile
and the connecting client is able to match the fingerprint
with that of the key presented.
.Pp
In this example, we are connecting a client to a server,
.Dq host.example.com .
The SSHFP resource records should first be added to the zonefile for
host.example.com:
.Bd -literal -offset indent
$ ssh-keygen -r host.example.com.
.Ed
.Pp
The output lines will have to be added to the zonefile.
To check that the zone is answering fingerprint queries:
.Pp
.Dl $ dig -t SSHFP host.example.com
.Pp
Finally the client connects:
.Bd -literal -offset indent
$ ssh -o "VerifyHostKeyDNS ask" host.example.com
[...]
Matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
.Ed
.Pp
See the
.Cm VerifyHostKeyDNS
option in
.Xr ssh_config 5
for more information.
.Sh SSH-BASED VIRTUAL PRIVATE NETWORKS
.Nm
contains support for Virtual Private Network (VPN) tunnelling
using the
.Xr tun 4
network pseudo-device,
allowing two networks to be joined securely.
The
.Xr sshd_config 5
configuration option
.Cm PermitTunnel
controls whether the server supports this,
and at what level (layer 2 or 3 traffic).
.Pp
The following example would connect client network 10.0.50.0/24
with remote network 10.0.99.0/24 using a point-to-point connection
from 10.1.1.1 to 10.1.1.2,
provided that the SSH server running on the gateway to the remote network,
at 192.168.1.15, allows it.
.Pp
On the client:
.Bd -literal -offset indent
# ssh -f -w 0:1 192.168.1.15 true
# ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252
# route add 10.0.99.0/24 10.1.1.2
.Ed
.Pp
On the server:
.Bd -literal -offset indent
# ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252
# route add 10.0.50.0/24 10.1.1.1
.Ed
.Pp
Client access may be more finely tuned via the
.Pa /root/.ssh/authorized_keys
file (see below) and the
.Cm PermitRootLogin
server option.
The following entry would permit connections on
.Xr tun 4
device 1 from user
.Dq jane
and on tun device 2 from user
.Dq john ,
if
.Cm PermitRootLogin
is set to
.Dq forced-commands-only :
.Bd -literal -offset 2n
tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane
tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john
.Ed
.Pp
Since an SSH-based setup entails a fair amount of overhead,
it may be more suited to temporary setups,
such as for wireless VPNs.
More permanent VPNs are better provided by tools such as
.Xr ipsecctl 8
and
.Xr isakmpd 8 .
.Sh ENVIRONMENT
.Nm
will normally set the following environment variables:
.Bl -tag -width "SSH_ORIGINAL_COMMAND"
.It Ev DISPLAY
The
.Ev DISPLAY
variable indicates the location of the X11 server.
It is automatically set by
.Nm
to point to a value of the form
.Dq hostname:n ,
where
.Dq hostname
indicates the host where the shell runs, and
.Sq n
is an integer \*(Ge 1.
.Nm
uses this special value to forward X11 connections over the secure
channel.
The user should normally not set
.Ev DISPLAY
explicitly, as that
will render the X11 connection insecure (and will require the user to
manually copy any required authorization cookies).
.It Ev HOME
Set to the path of the user's home directory.
.It Ev LOGNAME
Synonym for
.Ev USER ;
set for compatibility with systems that use this variable.
.It Ev MAIL
Set to the path of the user's mailbox.
.It Ev PATH
Set to the default
.Ev PATH ,
as specified when compiling
.Nm .
.It Ev SSH_ASKPASS
If
.Nm
needs a passphrase, it will read the passphrase from the current
terminal if it was run from a terminal.
If
.Nm
does not have a terminal associated with it but
.Ev DISPLAY
and
.Ev SSH_ASKPASS
are set, it will execute the program specified by
.Ev SSH_ASKPASS
and open an X11 window to read the passphrase.
This is particularly useful when calling
.Nm
from a
.Pa .xsession
or related script.
(Note that on some machines it
may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
.It Ev SSH_AUTH_SOCK
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
.It Ev SSH_CONNECTION
Identifies the client and server ends of the connection.
The variable contains
four space-separated values: client IP address, client port number,
server IP address, and server port number.
.It Ev SSH_ORIGINAL_COMMAND
This variable contains the original command line if a forced command
is executed.
It can be used to extract the original arguments.
.It Ev SSH_TTY
This is set to the name of the tty (path to the device) associated
with the current shell or command.
If the current session has no tty,
this variable is not set.
.It Ev SSH_TUNNEL
Optionally set by
.Xr sshd 8
to contain the interface names assigned if tunnel forwarding was
requested by the client.
.It Ev SSH_USER_AUTH
Optionally set by
.Xr sshd 8 ,
this variable may contain a pathname to a file that lists the authentication
methods successfully used when the session was established, including any
public keys that were used.
.It Ev TZ
This variable is set to indicate the present time zone if it
was set when the daemon was started (i.e. the daemon passes the value
on to new connections).
.It Ev USER
Set to the name of the user logging in.
.El
.Pp
Additionally,
.Nm
reads
.Pa ~/.ssh/environment ,
and adds lines of the format
.Dq VARNAME=value
to the environment if the file exists and users are allowed to
change their environment.
For more information, see the
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
This file is used for host-based authentication (see above).
On some machines this file may need to be
world-readable if the user's home directory is on an NFS partition,
because
.Xr sshd 8
reads it as root.
Additionally, this file must be owned by the user,
and must not have write permissions for anyone else.
The recommended
permission for most machines is read/write for the user, and not
accessible by others.
.Pp
.It Pa ~/.shosts
This file is used in exactly the same way as
.Pa .rhosts ,
but allows host-based authentication without permitting login with
rlogin/rsh.
.Pp
.It Pa ~/.ssh/
This directory is the default location for all user-specific configuration
and authentication information.
There is no general requirement to keep the entire contents of this directory
secret, but the recommended permissions are read/write/execute for the user,
and not accessible by others.
.Pp
.It Pa ~/.ssh/authorized_keys
Lists the public keys (DSA, ECDSA, Ed25519, RSA)
that can be used for logging in as this user.
The format of this file is described in the
.Xr sshd 8
manual page.
This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others.
.Pp
.It Pa ~/.ssh/config
This is the per-user configuration file.
The file format and configuration options are described in
.Xr ssh_config 5 .
Because of the potential for abuse, this file must have strict permissions:
read/write for the user, and not writable by others.
.Pp
.It Pa ~/.ssh/environment
Contains additional definitions for environment variables; see
.Sx ENVIRONMENT ,
above.
.Pp
.It Pa ~/.ssh/id_dsa
.It Pa ~/.ssh/id_ecdsa
.It Pa ~/.ssh/id_ed25519
.It Pa ~/.ssh/id_rsa
Contains the private key for authentication.
These files
contain sensitive data and should be readable by the user but not
accessible by others (read/write/execute).
.Nm
will simply ignore a private key file if it is accessible by others.
It is possible to specify a passphrase when
generating the key which will be used to encrypt the
sensitive part of this file using AES-128.
.Pp
.It Pa ~/.ssh/id_dsa.pub
.It Pa ~/.ssh/id_ecdsa.pub
.It Pa ~/.ssh/id_ed25519.pub
.It Pa ~/.ssh/id_rsa.pub
Contains the public key for authentication.
These files are not
sensitive and can (but need not) be readable by anyone.
.Pp
.It Pa ~/.ssh/known_hosts
Contains a list of host keys for all hosts the user has logged into
that are not already in the systemwide list of known host keys.
See
.Xr sshd 8
for further details of the format of this file.
.Pp
.It Pa ~/.ssh/rc
Commands in this file are executed by
.Nm
when the user logs in, just before the user's shell (or command) is
started.
See the
.Xr sshd 8
manual page for more information.
.Pp
.It Pa /etc/hosts.equiv
This file is for host-based authentication (see above).
It should only be writable by root.
.Pp
.It Pa /etc/shosts.equiv
This file is used in exactly the same way as
.Pa hosts.equiv ,
but allows host-based authentication without permitting login with
rlogin/rsh.
.Pp
.It Pa /etc/ssh/ssh_config
Systemwide configuration file.
The file format and configuration options are described in
.Xr ssh_config 5 .
.Pp
.It Pa /etc/ssh/ssh_host_key
.It Pa /etc/ssh/ssh_host_dsa_key
.It Pa /etc/ssh/ssh_host_ecdsa_key
.It Pa /etc/ssh/ssh_host_ed25519_key
.It Pa /etc/ssh/ssh_host_rsa_key
These files contain the private parts of the host keys
and are used for host-based authentication.
.Pp
.It Pa /etc/ssh/ssh_known_hosts
Systemwide list of known host keys.
This file should be prepared by the
system administrator to contain the public host keys of all machines in the
organization.
It should be world-readable.
See
.Xr sshd 8
for further details of the format of this file.
.Pp
.It Pa /etc/ssh/sshrc
Commands in this file are executed by
.Nm
when the user logs in, just before the user's shell (or command) is started.
See the
.Xr sshd 8
manual page for more information.
.El
.Sh EXIT STATUS
.Nm
exits with the exit status of the remote command or with 255
if an error occurred.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh-keyscan 1 ,
.Xr tun 4 ,
.Xr ssh_config 5 ,
.Xr ssh-keysign 8 ,
.Xr sshd 8
.Sh STANDARDS
.Rs
.%A S. Lehtinen
.%A C. Lonvick
.%D January 2006
.%R RFC 4250
.%T The Secure Shell (SSH) Protocol Assigned Numbers
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4251
.%T The Secure Shell (SSH) Protocol Architecture
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4252
.%T The Secure Shell (SSH) Authentication Protocol
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4253
.%T The Secure Shell (SSH) Transport Layer Protocol
.Re
.Pp
.Rs
.%A T. Ylonen
.%A C. Lonvick
.%D January 2006
.%R RFC 4254
.%T The Secure Shell (SSH) Connection Protocol
.Re
.Pp
.Rs
.%A J. Schlyter
.%A W. Griffin
.%D January 2006
.%R RFC 4255
.%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
.Re
.Pp
.Rs
.%A F. Cusack
.%A M. Forssen
.%D January 2006
.%R RFC 4256
.%T Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
.Re
.Pp
.Rs
.%A J. Galbraith
.%A P. Remaker
.%D January 2006
.%R RFC 4335
.%T The Secure Shell (SSH) Session Channel Break Extension
.Re
.Pp
.Rs
.%A M. Bellare
.%A T. Kohno
.%A C. Namprempre
.%D January 2006
.%R RFC 4344
.%T The Secure Shell (SSH) Transport Layer Encryption Modes
.Re
.Pp
.Rs
.%A B. Harris
.%D January 2006
.%R RFC 4345
.%T Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
.Re
.Pp
.Rs
.%A M. Friedl
.%A N. Provos
.%A W. Simpson
.%D March 2006
.%R RFC 4419
.%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol
.Re
.Pp
.Rs
.%A J. Galbraith
.%A R. Thayer
.%D November 2006
.%R RFC 4716
.%T The Secure Shell (SSH) Public Key File Format
.Re
.Pp
.Rs
.%A D. Stebila
.%A J. Green
.%D December 2009
.%R RFC 5656
.%T Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
.Re
.Pp
.Rs
.%A A. Perrig
.%A D. Song
.%D 1999
.%O International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)
.%T Hash Visualization: a New Technique to improve Real-World Security
.Re
.Sh AUTHORS
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by Tatu Ylonen.
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
Theo de Raadt and Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
Markus Friedl contributed the support for SSH
protocol versions 1.5 and 2.0.
diff --git a/ssh.c b/ssh.c
index 0777c31e42b7..91e7c3511ded 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,2145 +1,2164 @@
-/* $OpenBSD: ssh.c,v 1.494 2018/10/03 06:38:35 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.500 2019/01/19 21:43:56 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Ssh client program. This program can be used to log into a remote machine.
* The software supports strong authentication, encryption, and forwarding
* of X11, TCP/IP, and authentication connections.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 1999 Niels Provos. All rights reserved.
* Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved.
*
* Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
* in Canada (German citizen).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <locale.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "canohost.h"
#include "compat.h"
#include "cipher.h"
#include "digest.h"
#include "packet.h"
#include "sshbuf.h"
#include "channels.h"
#include "sshkey.h"
#include "authfd.h"
#include "authfile.h"
#include "pathnames.h"
#include "dispatch.h"
#include "clientloop.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "sshconnect.h"
#include "kex.h"
#include "mac.h"
#include "sshpty.h"
#include "match.h"
#include "msg.h"
#include "version.h"
#include "ssherr.h"
#include "myproposal.h"
#include "utf8.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
#endif
extern char *__progname;
/* Saves a copy of argv for setproctitle emulation */
#ifndef HAVE_SETPROCTITLE
static char **saved_av;
#endif
/* Flag indicating whether debug mode is on. May be set on the command line. */
int debug_flag = 0;
/* Flag indicating whether a tty should be requested */
int tty_flag = 0;
/* don't exec a shell */
int no_shell_flag = 0;
/*
* Flag indicating that nothing should be read from stdin. This can be set
* on the command line.
*/
int stdin_null_flag = 0;
/*
* Flag indicating that the current process should be backgrounded and
* a new slave launched in the foreground for ControlPersist.
*/
int need_controlpersist_detach = 0;
/* Copies of flags for ControlPersist foreground slave */
int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
/*
* Flag indicating that ssh should fork after authentication. This is useful
* so that the passphrase can be entered manually, and then ssh goes to the
* background.
*/
int fork_after_authentication_flag = 0;
/*
* General data structure for command line options and options configurable
* in configuration files. See readconf.h.
*/
Options options;
/* optional user configfile */
char *config = NULL;
/*
* Name of the host we are connecting to. This is the name given on the
* command line, or the HostName specified for the user-supplied name in a
* configuration file.
*/
char *host;
/* Various strings used to to percent_expand() arguments */
static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
static char uidstr[32], *host_arg, *conn_hash_hex;
/* socket address the host resolves to */
struct sockaddr_storage hostaddr;
/* Private host keys. */
Sensitive sensitive_data;
/* command to be executed */
struct sshbuf *command;
/* Should we execute a command or invoke a subsystem? */
int subsystem_flag = 0;
/* # of replies received for global requests */
static int remote_forward_confirms_received = 0;
/* mux.c */
extern int muxserver_sock;
extern u_int muxclient_command;
/* Prints a help message to the user. This function never returns. */
static void
usage(void)
{
fprintf(stderr,
"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]\n"
" [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]\n"
" [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]\n"
" [-i identity_file] [-J [user@]host[:port]] [-L address]\n"
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n"
" [-w local_tun[:remote_tun]] destination [command]\n"
);
exit(255);
}
static int ssh_session2(struct ssh *, struct passwd *);
static void load_public_identity_files(struct passwd *);
static void main_sigchld_handler(int);
/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
static void
tilde_expand_paths(char **paths, u_int num_paths)
{
u_int i;
char *cp;
for (i = 0; i < num_paths; i++) {
cp = tilde_expand_filename(paths[i], getuid());
free(paths[i]);
paths[i] = cp;
}
}
/*
* Attempt to resolve a host name / port to a set of addresses and
* optionally return any CNAMEs encountered along the way.
* Returns NULL on failure.
* NB. this function must operate with a options having undefined members.
*/
static struct addrinfo *
resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
{
char strport[NI_MAXSERV];
struct addrinfo hints, *res;
int gaierr, loglevel = SYSLOG_LEVEL_DEBUG1;
if (port <= 0)
port = default_ssh_port();
snprintf(strport, sizeof strport, "%d", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = options.address_family == -1 ?
AF_UNSPEC : options.address_family;
hints.ai_socktype = SOCK_STREAM;
if (cname != NULL)
hints.ai_flags = AI_CANONNAME;
if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) {
if (logerr || (gaierr != EAI_NONAME && gaierr != EAI_NODATA))
loglevel = SYSLOG_LEVEL_ERROR;
do_log2(loglevel, "%s: Could not resolve hostname %.100s: %s",
__progname, name, ssh_gai_strerror(gaierr));
return NULL;
}
if (cname != NULL && res->ai_canonname != NULL) {
if (strlcpy(cname, res->ai_canonname, clen) >= clen) {
error("%s: host \"%s\" cname \"%s\" too long (max %lu)",
__func__, name, res->ai_canonname, (u_long)clen);
if (clen > 0)
*cname = '\0';
}
}
return res;
}
/* Returns non-zero if name can only be an address and not a hostname */
static int
is_addr_fast(const char *name)
{
return (strchr(name, '%') != NULL || strchr(name, ':') != NULL ||
strspn(name, "0123456789.") == strlen(name));
}
/* Returns non-zero if name represents a valid, single address */
static int
is_addr(const char *name)
{
char strport[NI_MAXSERV];
struct addrinfo hints, *res;
if (is_addr_fast(name))
return 1;
snprintf(strport, sizeof strport, "%u", default_ssh_port());
memset(&hints, 0, sizeof(hints));
hints.ai_family = options.address_family == -1 ?
AF_UNSPEC : options.address_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
if (getaddrinfo(name, strport, &hints, &res) != 0)
return 0;
if (res == NULL || res->ai_next != NULL) {
freeaddrinfo(res);
return 0;
}
freeaddrinfo(res);
return 1;
}
/*
* Attempt to resolve a numeric host address / port to a single address.
* Returns a canonical address string.
* Returns NULL on failure.
* NB. this function must operate with a options having undefined members.
*/
static struct addrinfo *
resolve_addr(const char *name, int port, char *caddr, size_t clen)
{
char addr[NI_MAXHOST], strport[NI_MAXSERV];
struct addrinfo hints, *res;
int gaierr;
if (port <= 0)
port = default_ssh_port();
snprintf(strport, sizeof strport, "%u", port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = options.address_family == -1 ?
AF_UNSPEC : options.address_family;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) {
debug2("%s: could not resolve name %.100s as address: %s",
__func__, name, ssh_gai_strerror(gaierr));
return NULL;
}
if (res == NULL) {
debug("%s: getaddrinfo %.100s returned no addresses",
__func__, name);
return NULL;
}
if (res->ai_next != NULL) {
debug("%s: getaddrinfo %.100s returned multiple addresses",
__func__, name);
goto fail;
}
if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen,
addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) {
debug("%s: Could not format address for name %.100s: %s",
__func__, name, ssh_gai_strerror(gaierr));
goto fail;
}
if (strlcpy(caddr, addr, clen) >= clen) {
error("%s: host \"%s\" addr \"%s\" too long (max %lu)",
__func__, name, addr, (u_long)clen);
if (clen > 0)
*caddr = '\0';
fail:
freeaddrinfo(res);
return NULL;
}
return res;
}
/*
* Check whether the cname is a permitted replacement for the hostname
* and perform the replacement if it is.
* NB. this function must operate with a options having undefined members.
*/
static int
check_follow_cname(int direct, char **namep, const char *cname)
{
int i;
struct allowed_cname *rule;
if (*cname == '\0' || options.num_permitted_cnames == 0 ||
strcmp(*namep, cname) == 0)
return 0;
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
return 0;
/*
* Don't attempt to canonicalize names that will be interpreted by
* a proxy or jump host unless the user specifically requests so.
*/
if (!direct &&
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
return 0;
debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
for (i = 0; i < options.num_permitted_cnames; i++) {
rule = options.permitted_cnames + i;
if (match_pattern_list(*namep, rule->source_list, 1) != 1 ||
match_pattern_list(cname, rule->target_list, 1) != 1)
continue;
verbose("Canonicalized DNS aliased hostname "
"\"%s\" => \"%s\"", *namep, cname);
free(*namep);
*namep = xstrdup(cname);
return 1;
}
return 0;
}
/*
* Attempt to resolve the supplied hostname after applying the user's
* canonicalization rules. Returns the address list for the host or NULL
* if no name was found after canonicalization.
* NB. this function must operate with a options having undefined members.
*/
static struct addrinfo *
resolve_canonicalize(char **hostp, int port)
{
int i, direct, ndots;
char *cp, *fullhost, newname[NI_MAXHOST];
struct addrinfo *addrs;
/*
* Attempt to canonicalise addresses, regardless of
* whether hostname canonicalisation was requested
*/
if ((addrs = resolve_addr(*hostp, port,
newname, sizeof(newname))) != NULL) {
debug2("%s: hostname %.100s is address", __func__, *hostp);
if (strcasecmp(*hostp, newname) != 0) {
debug2("%s: canonicalised address \"%s\" => \"%s\"",
__func__, *hostp, newname);
free(*hostp);
*hostp = xstrdup(newname);
}
return addrs;
}
/*
* If this looks like an address but didn't parse as one, it might
* be an address with an invalid interface scope. Skip further
* attempts at canonicalisation.
*/
if (is_addr_fast(*hostp)) {
debug("%s: hostname %.100s is an unrecognised address",
__func__, *hostp);
return NULL;
}
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
return NULL;
/*
* Don't attempt to canonicalize names that will be interpreted by
* a proxy unless the user specifically requests so.
*/
direct = option_clear_or_none(options.proxy_command) &&
options.jump_host == NULL;
if (!direct &&
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
return NULL;
/* If domain name is anchored, then resolve it now */
if ((*hostp)[strlen(*hostp) - 1] == '.') {
debug3("%s: name is fully qualified", __func__);
fullhost = xstrdup(*hostp);
if ((addrs = resolve_host(fullhost, port, 0,
newname, sizeof(newname))) != NULL)
goto found;
free(fullhost);
goto notfound;
}
/* Don't apply canonicalization to sufficiently-qualified hostnames */
ndots = 0;
for (cp = *hostp; *cp != '\0'; cp++) {
if (*cp == '.')
ndots++;
}
if (ndots > options.canonicalize_max_dots) {
debug3("%s: not canonicalizing hostname \"%s\" (max dots %d)",
__func__, *hostp, options.canonicalize_max_dots);
return NULL;
}
/* Attempt each supplied suffix */
for (i = 0; i < options.num_canonical_domains; i++) {
*newname = '\0';
xasprintf(&fullhost, "%s.%s.", *hostp,
options.canonical_domains[i]);
debug3("%s: attempting \"%s\" => \"%s\"", __func__,
*hostp, fullhost);
if ((addrs = resolve_host(fullhost, port, 0,
newname, sizeof(newname))) == NULL) {
free(fullhost);
continue;
}
found:
/* Remove trailing '.' */
fullhost[strlen(fullhost) - 1] = '\0';
/* Follow CNAME if requested */
if (!check_follow_cname(direct, &fullhost, newname)) {
debug("Canonicalized hostname \"%s\" => \"%s\"",
*hostp, fullhost);
}
free(*hostp);
*hostp = fullhost;
return addrs;
}
notfound:
if (!options.canonicalize_fallback_local)
fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
debug2("%s: host %s not found in any suffix", __func__, *hostp);
return NULL;
}
/*
* Check the result of hostkey loading, ignoring some errors and
* fatal()ing for others.
*/
static void
check_load(int r, const char *path, const char *message)
{
switch (r) {
case 0:
break;
case SSH_ERR_INTERNAL_ERROR:
case SSH_ERR_ALLOC_FAIL:
fatal("load %s \"%s\": %s", message, path, ssh_err(r));
case SSH_ERR_SYSTEM_ERROR:
/* Ignore missing files */
if (errno == ENOENT)
break;
/* FALLTHROUGH */
default:
error("load %s \"%s\": %s", message, path, ssh_err(r));
break;
}
}
/*
* Read per-user configuration file. Ignore the system wide config
* file if the user specifies a config file on the command line.
*/
static void
-process_config_files(const char *host_name, struct passwd *pw, int post_canon)
+process_config_files(const char *host_name, struct passwd *pw, int final_pass,
+ int *want_final_pass)
{
char buf[PATH_MAX];
int r;
if (config != NULL) {
if (strcasecmp(config, "none") != 0 &&
!read_config_file(config, pw, host, host_name, &options,
- SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0)))
+ SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0),
+ want_final_pass))
fatal("Can't open user config file %.100s: "
"%.100s", config, strerror(errno));
} else {
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir,
_PATH_SSH_USER_CONFFILE);
if (r > 0 && (size_t)r < sizeof(buf))
(void)read_config_file(buf, pw, host, host_name,
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF |
- (post_canon ? SSHCONF_POSTCANON : 0));
+ (final_pass ? SSHCONF_FINAL : 0), want_final_pass);
/* Read systemwide configuration file after user config. */
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
host, host_name, &options,
- post_canon ? SSHCONF_POSTCANON : 0);
+ final_pass ? SSHCONF_FINAL : 0, want_final_pass);
}
}
/* Rewrite the port number in an addrinfo list of addresses */
static void
set_addrinfo_port(struct addrinfo *addrs, int port)
{
struct addrinfo *addr;
for (addr = addrs; addr != NULL; addr = addr->ai_next) {
switch (addr->ai_family) {
case AF_INET:
((struct sockaddr_in *)addr->ai_addr)->
sin_port = htons(port);
break;
case AF_INET6:
((struct sockaddr_in6 *)addr->ai_addr)->
sin6_port = htons(port);
break;
}
}
}
/*
* Main program for the ssh client.
*/
int
main(int ac, char **av)
{
struct ssh *ssh = NULL;
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
- int was_addr, config_test = 0, opt_terminated = 0;
+ int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
char cname[NI_MAXHOST];
struct stat st;
struct passwd *pw;
extern int optind, optreset;
extern char *optarg;
struct Forward fwd;
struct addrinfo *addrs = NULL;
struct ssh_digest_ctx *md;
u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
__progname = ssh_get_progname(av[0]);
#ifndef HAVE_SETPROCTITLE
/* Prepare for later setproctitle emulation */
/* Save argv so it isn't clobbered by setproctitle() emulation */
saved_av = xcalloc(ac + 1, sizeof(*saved_av));
for (i = 0; i < ac; i++)
saved_av[i] = xstrdup(av[i]);
saved_av[i] = NULL;
compat_init_setproctitle(ac, av);
av = saved_av;
#endif
+ seed_rng();
+
/*
* Discard other fds that are hanging around. These can cause problem
* with backgrounded ssh processes started by ControlPersist.
*/
closefrom(STDERR_FILENO + 1);
/* Get user data. */
pw = getpwuid(getuid());
if (!pw) {
logit("No user exists for uid %lu", (u_long)getuid());
exit(255);
}
/* Take a copy of the returned structure. */
pw = pwcopy(pw);
/*
* Set our umask to something reasonable, as some files are created
* with the default umask. This will make them world-readable but
* writable only by the owner, which is ok for all files for which we
* don't set the modes explicitly.
*/
umask(022);
msetlocale();
/*
* Initialize option structure to indicate that no values have been
* set.
*/
initialize_options(&options);
/*
* Prepare main ssh transport/connection structures
*/
if ((ssh = ssh_alloc_session_state()) == NULL)
fatal("Couldn't allocate session state");
channel_init_channels(ssh);
- active_state = ssh; /* XXX legacy API compat */
/* Parse command-line arguments. */
host = NULL;
use_syslog = 0;
logfile = NULL;
argv0 = av[0];
again:
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
"AB:CD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
switch (opt) {
case '1':
fatal("SSH protocol v.1 is no longer supported");
break;
case '2':
/* Ignored */
break;
case '4':
options.address_family = AF_INET;
break;
case '6':
options.address_family = AF_INET6;
break;
case 'n':
stdin_null_flag = 1;
break;
case 'f':
fork_after_authentication_flag = 1;
stdin_null_flag = 1;
break;
case 'x':
options.forward_x11 = 0;
break;
case 'X':
options.forward_x11 = 1;
break;
case 'y':
use_syslog = 1;
break;
case 'E':
logfile = optarg;
break;
case 'G':
config_test = 1;
break;
case 'Y':
options.forward_x11 = 1;
options.forward_x11_trusted = 1;
break;
case 'g':
options.fwd_opts.gateway_ports = 1;
break;
case 'O':
if (options.stdio_forward_host != NULL)
fatal("Cannot specify multiplexing "
"command with -W");
else if (muxclient_command != 0)
fatal("Multiplexing command already specified");
if (strcmp(optarg, "check") == 0)
muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK;
else if (strcmp(optarg, "forward") == 0)
muxclient_command = SSHMUX_COMMAND_FORWARD;
else if (strcmp(optarg, "exit") == 0)
muxclient_command = SSHMUX_COMMAND_TERMINATE;
else if (strcmp(optarg, "stop") == 0)
muxclient_command = SSHMUX_COMMAND_STOP;
else if (strcmp(optarg, "cancel") == 0)
muxclient_command = SSHMUX_COMMAND_CANCEL_FWD;
else if (strcmp(optarg, "proxy") == 0)
muxclient_command = SSHMUX_COMMAND_PROXY;
else
fatal("Invalid multiplex command.");
break;
case 'P': /* deprecated */
break;
case 'Q':
cp = NULL;
if (strcmp(optarg, "cipher") == 0)
cp = cipher_alg_list('\n', 0);
else if (strcmp(optarg, "cipher-auth") == 0)
cp = cipher_alg_list('\n', 1);
else if (strcmp(optarg, "mac") == 0)
cp = mac_alg_list('\n');
else if (strcmp(optarg, "kex") == 0)
cp = kex_alg_list('\n');
else if (strcmp(optarg, "key") == 0)
cp = sshkey_alg_list(0, 0, 0, '\n');
else if (strcmp(optarg, "key-cert") == 0)
cp = sshkey_alg_list(1, 0, 0, '\n');
else if (strcmp(optarg, "key-plain") == 0)
cp = sshkey_alg_list(0, 1, 0, '\n');
else if (strcmp(optarg, "sig") == 0)
cp = sshkey_alg_list(0, 1, 1, '\n');
else if (strcmp(optarg, "protocol-version") == 0)
cp = xstrdup("2");
else if (strcmp(optarg, "help") == 0) {
cp = xstrdup(
"cipher\ncipher-auth\nkex\nkey\n"
"key-cert\nkey-plain\nmac\n"
"protocol-version\nsig");
}
if (cp == NULL)
fatal("Unsupported query \"%s\"", optarg);
printf("%s\n", cp);
free(cp);
exit(0);
break;
case 'a':
options.forward_agent = 0;
break;
case 'A':
options.forward_agent = 1;
break;
case 'k':
options.gss_deleg_creds = 0;
break;
case 'K':
options.gss_authentication = 1;
options.gss_deleg_creds = 1;
break;
case 'i':
p = tilde_expand_filename(optarg, getuid());
if (stat(p, &st) < 0)
fprintf(stderr, "Warning: Identity file %s "
"not accessible: %s.\n", p,
strerror(errno));
else
add_identity_file(&options, NULL, p, 1);
free(p);
break;
case 'I':
#ifdef ENABLE_PKCS11
free(options.pkcs11_provider);
options.pkcs11_provider = xstrdup(optarg);
#else
fprintf(stderr, "no support for PKCS#11.\n");
#endif
break;
case 'J':
if (options.jump_host != NULL)
fatal("Only a single -J option permitted");
if (options.proxy_command != NULL)
fatal("Cannot specify -J with ProxyCommand");
if (parse_jump(optarg, &options, 1) == -1)
fatal("Invalid -J argument");
options.proxy_command = xstrdup("none");
break;
case 't':
if (options.request_tty == REQUEST_TTY_YES)
options.request_tty = REQUEST_TTY_FORCE;
else
options.request_tty = REQUEST_TTY_YES;
break;
case 'v':
if (debug_flag == 0) {
debug_flag = 1;
options.log_level = SYSLOG_LEVEL_DEBUG1;
} else {
if (options.log_level < SYSLOG_LEVEL_DEBUG3) {
debug_flag++;
options.log_level++;
}
}
break;
case 'V':
fprintf(stderr, "%s, %s\n",
SSH_RELEASE,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
if (opt == 'V')
exit(0);
break;
case 'w':
if (options.tun_open == -1)
options.tun_open = SSH_TUNMODE_DEFAULT;
options.tun_local = a2tun(optarg, &options.tun_remote);
if (options.tun_local == SSH_TUNID_ERR) {
fprintf(stderr,
"Bad tun device '%s'\n", optarg);
exit(255);
}
break;
case 'W':
if (options.stdio_forward_host != NULL)
fatal("stdio forward already specified");
if (muxclient_command != 0)
fatal("Cannot specify stdio forward with -O");
if (parse_forward(&fwd, optarg, 1, 0)) {
options.stdio_forward_host = fwd.listen_host;
options.stdio_forward_port = fwd.listen_port;
free(fwd.connect_host);
} else {
fprintf(stderr,
"Bad stdio forwarding specification '%s'\n",
optarg);
exit(255);
}
options.request_tty = REQUEST_TTY_NO;
no_shell_flag = 1;
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
break;
case 'e':
if (optarg[0] == '^' && optarg[2] == 0 &&
(u_char) optarg[1] >= 64 &&
(u_char) optarg[1] < 128)
options.escape_char = (u_char) optarg[1] & 31;
else if (strlen(optarg) == 1)
options.escape_char = (u_char) optarg[0];
else if (strcmp(optarg, "none") == 0)
options.escape_char = SSH_ESCAPECHAR_NONE;
else {
fprintf(stderr, "Bad escape character '%s'.\n",
optarg);
exit(255);
}
break;
case 'c':
if (!ciphers_valid(*optarg == '+' ?
optarg + 1 : optarg)) {
fprintf(stderr, "Unknown cipher type '%s'\n",
optarg);
exit(255);
}
free(options.ciphers);
options.ciphers = xstrdup(optarg);
break;
case 'm':
if (mac_valid(optarg)) {
free(options.macs);
options.macs = xstrdup(optarg);
} else {
fprintf(stderr, "Unknown mac type '%s'\n",
optarg);
exit(255);
}
break;
case 'M':
if (options.control_master == SSHCTL_MASTER_YES)
options.control_master = SSHCTL_MASTER_ASK;
else
options.control_master = SSHCTL_MASTER_YES;
break;
case 'p':
if (options.port == -1) {
options.port = a2port(optarg);
if (options.port <= 0) {
fprintf(stderr, "Bad port '%s'\n",
optarg);
exit(255);
}
}
break;
case 'l':
if (options.user == NULL)
options.user = optarg;
break;
case 'L':
if (parse_forward(&fwd, optarg, 0, 0))
add_local_forward(&options, &fwd);
else {
fprintf(stderr,
"Bad local forwarding specification '%s'\n",
optarg);
exit(255);
}
break;
case 'R':
if (parse_forward(&fwd, optarg, 0, 1) ||
parse_forward(&fwd, optarg, 1, 1)) {
add_remote_forward(&options, &fwd);
} else {
fprintf(stderr,
"Bad remote forwarding specification "
"'%s'\n", optarg);
exit(255);
}
break;
case 'D':
if (parse_forward(&fwd, optarg, 1, 0)) {
add_local_forward(&options, &fwd);
} else {
fprintf(stderr,
"Bad dynamic forwarding specification "
"'%s'\n", optarg);
exit(255);
}
break;
case 'C':
options.compression = 1;
break;
case 'N':
no_shell_flag = 1;
options.request_tty = REQUEST_TTY_NO;
break;
case 'T':
options.request_tty = REQUEST_TTY_NO;
break;
case 'o':
line = xstrdup(optarg);
if (process_config_line(&options, pw,
host ? host : "", host ? host : "", line,
"command-line", 0, NULL, SSHCONF_USERCONF) != 0)
exit(255);
free(line);
break;
case 's':
subsystem_flag = 1;
break;
case 'S':
free(options.control_path);
options.control_path = xstrdup(optarg);
break;
case 'b':
options.bind_address = optarg;
break;
case 'B':
options.bind_interface = optarg;
break;
case 'F':
config = optarg;
break;
default:
usage();
}
}
if (optind > 1 && strcmp(av[optind - 1], "--") == 0)
opt_terminated = 1;
ac -= optind;
av += optind;
if (ac > 0 && !host) {
int tport;
char *tuser;
switch (parse_ssh_uri(*av, &tuser, &host, &tport)) {
case -1:
usage();
break;
case 0:
if (options.user == NULL) {
options.user = tuser;
tuser = NULL;
}
free(tuser);
if (options.port == -1 && tport != -1)
options.port = tport;
break;
default:
p = xstrdup(*av);
cp = strrchr(p, '@');
if (cp != NULL) {
if (cp == p)
usage();
if (options.user == NULL) {
options.user = p;
p = NULL;
}
*cp++ = '\0';
host = xstrdup(cp);
free(p);
} else
host = p;
break;
}
if (ac > 1 && !opt_terminated) {
optind = optreset = 1;
goto again;
}
ac--, av++;
}
/* Check that we got a host name. */
if (!host)
usage();
host_arg = xstrdup(host);
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
- ERR_load_crypto_strings();
-#endif
-
/* Initialize the command to execute on remote host. */
if ((command = sshbuf_new()) == NULL)
fatal("sshbuf_new failed");
/*
* Save the command to execute on the remote host in a buffer. There
* is no limit on the length of the command, except by the maximum
* packet size. Also sets the tty flag if there is no command.
*/
if (!ac) {
/* No command specified - execute shell on a tty. */
if (subsystem_flag) {
fprintf(stderr,
"You must specify a subsystem to invoke.\n");
usage();
}
} else {
/* A command has been specified. Store it into the buffer. */
for (i = 0; i < ac; i++) {
if ((r = sshbuf_putf(command, "%s%s",
i ? " " : "", av[i])) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
/*
* Initialize "log" output. Since we are the client all output
* goes to stderr unless otherwise specified by -y or -E.
*/
if (use_syslog && logfile != NULL)
fatal("Can't specify both -y and -E");
if (logfile != NULL)
log_redirect_stderr_to(logfile);
log_init(argv0,
options.log_level == SYSLOG_LEVEL_NOT_SET ?
SYSLOG_LEVEL_INFO : options.log_level,
options.log_facility == SYSLOG_FACILITY_NOT_SET ?
SYSLOG_FACILITY_USER : options.log_facility,
!use_syslog);
if (debug_flag)
logit("%s, %s", SSH_RELEASE,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
/* Parse the configuration files */
- process_config_files(host_arg, pw, 0);
+ process_config_files(host_arg, pw, 0, &want_final_pass);
+ if (want_final_pass)
+ debug("configuration requests final Match pass");
/* Hostname canonicalisation needs a few options filled. */
fill_default_options_for_canonicalization(&options);
/* If the user has replaced the hostname then take it into use now */
if (options.hostname != NULL) {
/* NB. Please keep in sync with readconf.c:match_cfg_line() */
cp = percent_expand(options.hostname,
"h", host, (char *)NULL);
free(host);
host = cp;
free(options.hostname);
options.hostname = xstrdup(host);
}
/* Don't lowercase addresses, they will be explicitly canonicalised */
if ((was_addr = is_addr(host)) == 0)
lowercase(host);
/*
* Try to canonicalize if requested by configuration or the
* hostname is an address.
*/
if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr)
addrs = resolve_canonicalize(&host, options.port);
/*
* If CanonicalizePermittedCNAMEs have been specified but
* other canonicalization did not happen (by not being requested
* or by failing with fallback) then the hostname may still be changed
* as a result of CNAME following.
*
* Try to resolve the bare hostname name using the system resolver's
* usual search rules and then apply the CNAME follow rules.
*
* Skip the lookup if a ProxyCommand is being used unless the user
* has specifically requested canonicalisation for this case via
* CanonicalizeHostname=always
*/
direct = option_clear_or_none(options.proxy_command) &&
options.jump_host == NULL;
if (addrs == NULL && options.num_permitted_cnames != 0 && (direct ||
options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
if ((addrs = resolve_host(host, options.port,
direct, cname, sizeof(cname))) == NULL) {
/* Don't fatal proxied host names not in the DNS */
if (direct)
cleanup_exit(255); /* logged in resolve_host */
} else
check_follow_cname(direct, &host, cname);
}
/*
* If canonicalisation is enabled then re-parse the configuration
* files as new stanzas may match.
*/
- if (options.canonicalize_hostname != 0) {
- debug("Re-reading configuration after hostname "
- "canonicalisation");
+ if (options.canonicalize_hostname != 0 && !want_final_pass) {
+ debug("hostname canonicalisation enabled, "
+ "will re-parse configuration");
+ want_final_pass = 1;
+ }
+
+ if (want_final_pass) {
+ debug("re-parsing configuration");
free(options.hostname);
options.hostname = xstrdup(host);
- process_config_files(host_arg, pw, 1);
+ process_config_files(host_arg, pw, 1, NULL);
/*
* Address resolution happens early with canonicalisation
* enabled and the port number may have changed since, so
* reset it in address list
*/
if (addrs != NULL && options.port > 0)
set_addrinfo_port(addrs, options.port);
}
/* Fill configuration defaults. */
fill_default_options(&options);
/*
* If ProxyJump option specified, then construct a ProxyCommand now.
*/
if (options.jump_host != NULL) {
char port_s[8];
const char *sshbin = argv0;
/*
* Try to use SSH indicated by argv[0], but fall back to
* "ssh" if it appears unavailable.
*/
if (strchr(argv0, '/') != NULL && access(argv0, X_OK) != 0)
sshbin = "ssh";
/* Consistency check */
if (options.proxy_command != NULL)
fatal("inconsistent options: ProxyCommand+ProxyJump");
/* Never use FD passing for ProxyJump */
options.proxy_use_fdpass = 0;
snprintf(port_s, sizeof(port_s), "%d", options.jump_port);
xasprintf(&options.proxy_command,
"%s%s%s%s%s%s%s%s%s%s%.*s -W '[%%h]:%%p' %s",
sshbin,
/* Optional "-l user" argument if jump_user set */
options.jump_user == NULL ? "" : " -l ",
options.jump_user == NULL ? "" : options.jump_user,
/* Optional "-p port" argument if jump_port set */
options.jump_port <= 0 ? "" : " -p ",
options.jump_port <= 0 ? "" : port_s,
/* Optional additional jump hosts ",..." */
options.jump_extra == NULL ? "" : " -J ",
options.jump_extra == NULL ? "" : options.jump_extra,
/* Optional "-F" argumment if -F specified */
config == NULL ? "" : " -F ",
config == NULL ? "" : config,
/* Optional "-v" arguments if -v set */
debug_flag ? " -" : "",
debug_flag, "vvv",
/* Mandatory hostname */
options.jump_host);
debug("Setting implicit ProxyCommand from ProxyJump: %s",
options.proxy_command);
}
if (options.port == 0)
options.port = default_ssh_port();
channel_set_af(ssh, options.address_family);
/* Tidy and check options */
if (options.host_key_alias != NULL)
lowercase(options.host_key_alias);
if (options.proxy_command != NULL &&
strcmp(options.proxy_command, "-") == 0 &&
options.proxy_use_fdpass)
fatal("ProxyCommand=- and ProxyUseFDPass are incompatible");
if (options.control_persist &&
options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) {
debug("UpdateHostKeys=ask is incompatible with ControlPersist; "
"disabling");
options.update_hostkeys = 0;
}
if (options.connection_attempts <= 0)
fatal("Invalid number of ConnectionAttempts");
if (sshbuf_len(command) != 0 && options.remote_command != NULL)
fatal("Cannot execute command-line and remote command.");
/* Cannot fork to background if no command. */
if (fork_after_authentication_flag && sshbuf_len(command) == 0 &&
options.remote_command == NULL && !no_shell_flag)
fatal("Cannot fork into background without a command "
"to execute.");
/* reinit */
log_init(argv0, options.log_level, options.log_facility, !use_syslog);
if (options.request_tty == REQUEST_TTY_YES ||
options.request_tty == REQUEST_TTY_FORCE)
tty_flag = 1;
/* Allocate a tty by default if no command specified. */
if (sshbuf_len(command) == 0 && options.remote_command == NULL)
tty_flag = options.request_tty != REQUEST_TTY_NO;
/* Force no tty */
if (options.request_tty == REQUEST_TTY_NO ||
(muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY))
tty_flag = 0;
/* Do not allocate a tty if stdin is not a tty. */
if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
options.request_tty != REQUEST_TTY_FORCE) {
if (tty_flag)
logit("Pseudo-terminal will not be allocated because "
"stdin is not a terminal.");
tty_flag = 0;
}
- seed_rng();
-
if (options.user == NULL)
options.user = xstrdup(pw->pw_name);
/* Set up strings used to percent_expand() arguments */
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
strlcpy(shorthost, thishost, sizeof(shorthost));
shorthost[strcspn(thishost, ".")] = '\0';
snprintf(portstr, sizeof(portstr), "%d", options.port);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
ssh_digest_update(md, host, strlen(host)) < 0 ||
ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
fatal("%s: mux digest failed", __func__);
ssh_digest_free(md);
conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
/*
* Expand tokens in arguments. NB. LocalCommand is expanded later,
* after port-forwarding is set up, so it may pick up any local
* tunnel interface name allocated.
*/
if (options.remote_command != NULL) {
debug3("expanding RemoteCommand: %s", options.remote_command);
cp = options.remote_command;
options.remote_command = percent_expand(cp,
"C", conn_hash_hex,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
"i", uidstr,
"l", thishost,
"n", host_arg,
"p", portstr,
"r", options.user,
"u", pw->pw_name,
(char *)NULL);
debug3("expanded RemoteCommand: %s", options.remote_command);
free(cp);
if ((r = sshbuf_put(command, options.remote_command,
strlen(options.remote_command))) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
}
if (options.control_path != NULL) {
cp = tilde_expand_filename(options.control_path, getuid());
free(options.control_path);
options.control_path = percent_expand(cp,
"C", conn_hash_hex,
"L", shorthost,
"h", host,
"i", uidstr,
"l", thishost,
"n", host_arg,
"p", portstr,
"r", options.user,
"u", pw->pw_name,
"i", uidstr,
(char *)NULL);
free(cp);
}
if (config_test) {
dump_client_config(&options, host);
exit(0);
}
if (muxclient_command != 0 && options.control_path == NULL)
fatal("No ControlPath specified for \"-O\" command");
if (options.control_path != NULL) {
int sock;
if ((sock = muxclient(options.control_path)) >= 0) {
ssh_packet_set_connection(ssh, sock, sock);
- packet_set_mux();
+ ssh_packet_set_mux(ssh);
goto skip_connect;
}
}
/*
* If hostname canonicalisation was not enabled, then we may not
* have yet resolved the hostname. Do so now.
*/
if (addrs == NULL && options.proxy_command == NULL) {
debug2("resolving \"%s\" port %d", host, options.port);
if ((addrs = resolve_host(host, options.port, 1,
cname, sizeof(cname))) == NULL)
cleanup_exit(255); /* resolve_host logs the error */
}
timeout_ms = options.connection_timeout * 1000;
/* Open a connection to the remote host. */
if (ssh_connect(ssh, host, addrs, &hostaddr, options.port,
options.address_family, options.connection_attempts,
&timeout_ms, options.tcp_keep_alive) != 0)
exit(255);
if (addrs != NULL)
freeaddrinfo(addrs);
- packet_set_timeout(options.server_alive_interval,
+ ssh_packet_set_timeout(ssh, options.server_alive_interval,
options.server_alive_count_max);
- ssh = active_state; /* XXX */
-
if (timeout_ms > 0)
debug3("timeout: %d ms remain after connect", timeout_ms);
/*
* If we successfully made the connection and we have hostbased auth
* enabled, load the public keys so we can later use the ssh-keysign
* helper to sign challenges.
*/
sensitive_data.nkeys = 0;
sensitive_data.keys = NULL;
if (options.hostbased_authentication) {
sensitive_data.nkeys = 10;
sensitive_data.keys = xcalloc(sensitive_data.nkeys,
sizeof(struct sshkey));
/* XXX check errors? */
#define L_PUBKEY(p,o) do { \
if ((o) >= sensitive_data.nkeys) \
fatal("%s pubkey out of array bounds", __func__); \
check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
p, "pubkey"); \
} while (0)
#define L_CERT(p,o) do { \
if ((o) >= sensitive_data.nkeys) \
fatal("%s cert out of array bounds", __func__); \
check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
} while (0)
if (options.hostbased_authentication == 1) {
L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0);
L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1);
L_CERT(_PATH_HOST_RSA_KEY_FILE, 2);
L_CERT(_PATH_HOST_DSA_KEY_FILE, 3);
L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4);
L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5);
L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6);
L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7);
L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8);
L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9);
}
}
/* Create ~/.ssh * directory if it doesn't already exist. */
if (config == NULL) {
r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) < 0) {
#ifdef WITH_SELINUX
ssh_selinux_setfscreatecon(buf);
#endif
if (mkdir(buf, 0700) < 0)
error("Could not create directory '%.200s'.",
buf);
#ifdef WITH_SELINUX
ssh_selinux_setfscreatecon(NULL);
#endif
}
}
/* load options.identity_files */
load_public_identity_files(pw);
/* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */
if (options.identity_agent &&
strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) {
if (strcmp(options.identity_agent, "none") == 0) {
unsetenv(SSH_AUTHSOCKET_ENV_NAME);
} else {
p = tilde_expand_filename(options.identity_agent,
getuid());
cp = percent_expand(p,
"d", pw->pw_dir,
"h", host,
"i", uidstr,
"l", thishost,
"r", options.user,
"u", pw->pw_name,
(char *)NULL);
free(p);
/*
* If identity_agent represents an environment variable
* then recheck that it is valid (since processing with
* percent_expand() may have changed it) and substitute
* its value.
*/
if (cp[0] == '$') {
if (!valid_env_name(cp + 1)) {
fatal("Invalid IdentityAgent "
"environment variable name %s", cp);
}
if ((p = getenv(cp + 1)) == NULL)
unsetenv(SSH_AUTHSOCKET_ENV_NAME);
else
setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1);
} else {
/* identity_agent specifies a path directly */
setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
}
free(cp);
}
}
/* Expand ~ in known host file names. */
tilde_expand_paths(options.system_hostfiles,
options.num_system_hostfiles);
tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
signal(SIGCHLD, main_sigchld_handler);
/* 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);
- if (packet_connection_is_on_socket()) {
+ if (ssh_packet_connection_is_on_socket(ssh)) {
verbose("Authenticated to %s ([%s]:%d).", host,
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
} else {
verbose("Authenticated to %s (via proxy).", host);
}
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
for (i = 0; i < sensitive_data.nkeys; i++) {
if (sensitive_data.keys[i] != NULL) {
/* Destroys contents safely */
debug3("clear hostkey %d", i);
sshkey_free(sensitive_data.keys[i]);
sensitive_data.keys[i] = NULL;
}
}
free(sensitive_data.keys);
}
for (i = 0; i < options.num_identity_files; i++) {
free(options.identity_files[i]);
options.identity_files[i] = NULL;
if (options.identity_keys[i]) {
sshkey_free(options.identity_keys[i]);
options.identity_keys[i] = NULL;
}
}
for (i = 0; i < options.num_certificate_files; i++) {
free(options.certificate_files[i]);
options.certificate_files[i] = NULL;
}
skip_connect:
exit_status = ssh_session2(ssh, pw);
- packet_close();
+ ssh_packet_close(ssh);
if (options.control_path != NULL && muxserver_sock != -1)
unlink(options.control_path);
/* Kill ProxyCommand if it is running. */
ssh_kill_proxy_command();
return exit_status;
}
static void
control_persist_detach(void)
{
pid_t pid;
int devnull, keep_stderr;
debug("%s: backgrounding master process", __func__);
/*
* master (current process) into the background, and make the
* foreground process a client of the backgrounded master.
*/
switch ((pid = fork())) {
case -1:
fatal("%s: fork: %s", __func__, strerror(errno));
case 0:
/* Child: master process continues mainloop */
break;
default:
/* Parent: set up mux slave to connect to backgrounded master */
debug2("%s: background process is %ld", __func__, (long)pid);
stdin_null_flag = ostdin_null_flag;
options.request_tty = orequest_tty;
tty_flag = otty_flag;
close(muxserver_sock);
muxserver_sock = -1;
options.control_master = SSHCTL_MASTER_NO;
muxclient(options.control_path);
/* muxclient() doesn't return on success. */
fatal("Failed to connect to new control master");
}
if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
error("%s: open(\"/dev/null\"): %s", __func__,
strerror(errno));
} else {
keep_stderr = log_is_on_stderr() && debug_flag;
if (dup2(devnull, STDIN_FILENO) == -1 ||
dup2(devnull, STDOUT_FILENO) == -1 ||
(!keep_stderr && dup2(devnull, STDERR_FILENO) == -1))
error("%s: dup2: %s", __func__, strerror(errno));
if (devnull > STDERR_FILENO)
close(devnull);
}
daemon(1, 1);
setproctitle("%s [mux]", options.control_path);
}
/* Do fork() after authentication. Used by "ssh -f" */
static void
fork_postauth(void)
{
if (need_controlpersist_detach)
control_persist_detach();
debug("forking to background");
fork_after_authentication_flag = 0;
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
}
/* Callback for remote forward global requests */
static void
ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
{
struct Forward *rfwd = (struct Forward *)ctxt;
+ u_int port;
+ int r;
/* XXX verbose() on failure? */
debug("remote forward %s for: listen %s%s%d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_path ? rfwd->listen_path :
rfwd->listen_host ? rfwd->listen_host : "",
(rfwd->listen_path || rfwd->listen_host) ? ":" : "",
rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
if (type == SSH2_MSG_REQUEST_SUCCESS) {
- rfwd->allocated_port = packet_get_int();
- logit("Allocated port %u for remote forward to %s:%d",
- rfwd->allocated_port,
- rfwd->connect_host, rfwd->connect_port);
- channel_update_permission(ssh,
- rfwd->handle, rfwd->allocated_port);
+ if ((r = sshpkt_get_u32(ssh, &port)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
+ if (port > 65535) {
+ error("Invalid allocated port %u for remote "
+ "forward to %s:%d", port,
+ rfwd->connect_host, rfwd->connect_port);
+ /* Ensure failure processing runs below */
+ type = SSH2_MSG_REQUEST_FAILURE;
+ channel_update_permission(ssh,
+ rfwd->handle, -1);
+ } else {
+ rfwd->allocated_port = (int)port;
+ logit("Allocated port %u for remote "
+ "forward to %s:%d",
+ rfwd->allocated_port, rfwd->connect_host,
+ rfwd->connect_port);
+ channel_update_permission(ssh,
+ rfwd->handle, rfwd->allocated_port);
+ }
} else {
channel_update_permission(ssh, rfwd->handle, -1);
}
}
if (type == SSH2_MSG_REQUEST_FAILURE) {
if (options.exit_on_forward_failure) {
if (rfwd->listen_path != NULL)
fatal("Error: remote port forwarding failed "
"for listen path %s", rfwd->listen_path);
else
fatal("Error: remote port forwarding failed "
"for listen port %d", rfwd->listen_port);
} else {
if (rfwd->listen_path != NULL)
logit("Warning: remote port forwarding failed "
"for listen path %s", rfwd->listen_path);
else
logit("Warning: remote port forwarding failed "
"for listen port %d", rfwd->listen_port);
}
}
if (++remote_forward_confirms_received == options.num_remote_forwards) {
debug("All remote forwarding requests processed");
if (fork_after_authentication_flag)
fork_postauth();
}
}
static void
client_cleanup_stdio_fwd(struct ssh *ssh, int id, void *arg)
{
debug("stdio forwarding: done");
cleanup_exit(0);
}
static void
ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
{
if (!success)
fatal("stdio forwarding failed");
}
static void
ssh_init_stdio_forwarding(struct ssh *ssh)
{
Channel *c;
int in, out;
if (options.stdio_forward_host == NULL)
return;
debug3("%s: %s:%d", __func__, options.stdio_forward_host,
options.stdio_forward_port);
if ((in = dup(STDIN_FILENO)) < 0 ||
(out = dup(STDOUT_FILENO)) < 0)
fatal("channel_connect_stdio_fwd: dup() in/out failed");
if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
options.stdio_forward_port, in, out)) == NULL)
fatal("%s: channel_connect_stdio_fwd failed", __func__);
channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
}
static void
ssh_init_forwarding(struct ssh *ssh, char **ifname)
{
int success = 0;
int i;
/* Initiate local TCP/IP port forwardings. */
for (i = 0; i < options.num_local_forwards; i++) {
debug("Local connections to %.200s:%d forwarded to remote "
"address %.200s:%d",
(options.local_forwards[i].listen_path != NULL) ?
options.local_forwards[i].listen_path :
(options.local_forwards[i].listen_host == NULL) ?
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
options.local_forwards[i].listen_host,
options.local_forwards[i].listen_port,
(options.local_forwards[i].connect_path != NULL) ?
options.local_forwards[i].connect_path :
options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port);
success += channel_setup_local_fwd_listener(ssh,
&options.local_forwards[i], &options.fwd_opts);
}
if (i > 0 && success != i && options.exit_on_forward_failure)
fatal("Could not request local forwarding.");
if (i > 0 && success == 0)
error("Could not request local forwarding.");
/* Initiate remote TCP/IP port forwardings. */
for (i = 0; i < options.num_remote_forwards; i++) {
debug("Remote connections from %.200s:%d forwarded to "
"local address %.200s:%d",
(options.remote_forwards[i].listen_path != NULL) ?
options.remote_forwards[i].listen_path :
(options.remote_forwards[i].listen_host == NULL) ?
"LOCALHOST" : options.remote_forwards[i].listen_host,
options.remote_forwards[i].listen_port,
(options.remote_forwards[i].connect_path != NULL) ?
options.remote_forwards[i].connect_path :
options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port);
options.remote_forwards[i].handle =
channel_request_remote_forwarding(ssh,
&options.remote_forwards[i]);
if (options.remote_forwards[i].handle < 0) {
if (options.exit_on_forward_failure)
fatal("Could not request remote forwarding.");
else
logit("Warning: Could not request remote "
"forwarding.");
} else {
client_register_global_confirm(
ssh_confirm_remote_forward,
&options.remote_forwards[i]);
}
}
/* Initiate tunnel forwarding. */
if (options.tun_open != SSH_TUNMODE_NO) {
if ((*ifname = client_request_tun_fwd(ssh,
options.tun_open, options.tun_local,
options.tun_remote)) == NULL) {
if (options.exit_on_forward_failure)
fatal("Could not request tunnel forwarding.");
else
error("Could not request tunnel forwarding.");
}
}
}
static void
check_agent_present(void)
{
int r;
if (options.forward_agent) {
/* Clear agent forwarding if we don't have an agent. */
if ((r = ssh_get_authentication_socket(NULL)) != 0) {
options.forward_agent = 0;
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("ssh_get_authentication_socket: %s",
ssh_err(r));
}
}
}
static void
ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg)
{
extern char **environ;
const char *display;
- int interactive = tty_flag;
+ int r, interactive = tty_flag;
char *proto = NULL, *data = NULL;
if (!success)
return; /* No need for error message, channels code sens one */
display = getenv("DISPLAY");
if (display == NULL && options.forward_x11)
debug("X11 forwarding requested but DISPLAY not set");
if (options.forward_x11 && client_x11_get_proto(ssh, display,
options.xauth_location, options.forward_x11_trusted,
options.forward_x11_timeout, &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication "
"spoofing.");
x11_request_forwarding_with_spoofing(ssh, id, display, proto,
data, 1);
client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN);
/* XXX exit_on_forward_failure */
interactive = 1;
}
check_agent_present();
if (options.forward_agent) {
debug("Requesting authentication agent forwarding.");
channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
/* Tell the packet module whether this is an interactive session. */
- packet_set_interactive(interactive,
+ ssh_packet_set_interactive(ssh, interactive,
options.ip_qos_interactive, options.ip_qos_bulk);
client_session2_setup(ssh, id, tty_flag, subsystem_flag, getenv("TERM"),
NULL, fileno(stdin), command, environ);
}
/* open new channel for a session */
static int
ssh_session2_open(struct ssh *ssh)
{
Channel *c;
int window, packetmax, in, out, err;
if (stdin_null_flag) {
in = open(_PATH_DEVNULL, O_RDONLY);
} else {
in = dup(STDIN_FILENO);
}
out = dup(STDOUT_FILENO);
err = dup(STDERR_FILENO);
if (in < 0 || out < 0 || err < 0)
fatal("dup() in/out/err failed");
/* enable nonblocking unless tty */
if (!isatty(in))
set_nonblock(in);
if (!isatty(out))
set_nonblock(out);
if (!isatty(err))
set_nonblock(err);
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
if (tty_flag) {
window >>= 1;
packetmax >>= 1;
}
c = channel_new(ssh,
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE,
"client-session", /*nonblock*/0);
debug3("%s: channel_new: %d", __func__, c->self);
channel_send_open(ssh, c->self);
if (!no_shell_flag)
channel_register_open_confirm(ssh, c->self,
ssh_session2_setup, NULL);
return c->self;
}
static int
ssh_session2(struct ssh *ssh, struct passwd *pw)
{
- int devnull, id = -1;
+ int r, devnull, id = -1;
char *cp, *tun_fwd_ifname = NULL;
/* XXX should be pre-session */
if (!options.control_persist)
ssh_init_stdio_forwarding(ssh);
ssh_init_forwarding(ssh, &tun_fwd_ifname);
if (options.local_command != NULL) {
debug3("expanding LocalCommand: %s", options.local_command);
cp = options.local_command;
options.local_command = percent_expand(cp,
"C", conn_hash_hex,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
"i", uidstr,
"l", thishost,
"n", host_arg,
"p", portstr,
"r", options.user,
"u", pw->pw_name,
"T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
(char *)NULL);
debug3("expanded LocalCommand: %s", options.local_command);
free(cp);
}
/* Start listening for multiplex clients */
- if (!packet_get_mux())
+ if (!ssh_packet_get_mux(ssh))
muxserver_listen(ssh);
/*
* If we are in control persist mode and have a working mux listen
* socket, then prepare to background ourselves and have a foreground
* client attach as a control slave.
* NB. we must save copies of the flags that we override for
* the backgrounding, since we defer attachment of the slave until
* after the connection is fully established (in particular,
* async rfwd replies have been received for ExitOnForwardFailure).
*/
if (options.control_persist && muxserver_sock != -1) {
ostdin_null_flag = stdin_null_flag;
ono_shell_flag = no_shell_flag;
orequest_tty = options.request_tty;
otty_flag = tty_flag;
stdin_null_flag = 1;
no_shell_flag = 1;
tty_flag = 0;
if (!fork_after_authentication_flag)
need_controlpersist_detach = 1;
fork_after_authentication_flag = 1;
}
/*
* ControlPersist mux listen socket setup failed, attempt the
* stdio forward setup that we skipped earlier.
*/
if (options.control_persist && muxserver_sock == -1)
ssh_init_stdio_forwarding(ssh);
if (!no_shell_flag)
id = ssh_session2_open(ssh);
else {
- packet_set_interactive(
+ ssh_packet_set_interactive(ssh,
options.control_master == SSHCTL_MASTER_NO,
options.ip_qos_interactive, options.ip_qos_bulk);
}
/* If we don't expect to open a new session, then disallow it */
if (options.control_master == SSHCTL_MASTER_NO &&
(datafellows & SSH_NEW_OPENSSH)) {
debug("Requesting no-more-sessions@openssh.com");
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("no-more-sessions@openssh.com");
- packet_put_char(0);
- packet_send();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ "no-more-sessions@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal("%s: %s", __func__, ssh_err(r));
}
/* Execute a local command */
if (options.local_command != NULL &&
options.permit_local_command)
ssh_local_cmd(options.local_command);
/*
* stdout is now owned by the session channel; clobber it here
* so future channel closes are propagated to the local fd.
* NB. this can only happen after LocalCommand has completed,
* as it may want to write to stdout.
*/
if (!need_controlpersist_detach) {
if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1)
error("%s: open %s: %s", __func__,
_PATH_DEVNULL, strerror(errno));
if (dup2(devnull, STDOUT_FILENO) < 0)
fatal("%s: dup2() stdout failed", __func__);
if (devnull > STDERR_FILENO)
close(devnull);
}
/*
* If requested and we are not interested in replies to remote
* forwarding requests, then let ssh continue in the background.
*/
if (fork_after_authentication_flag) {
if (options.exit_on_forward_failure &&
options.num_remote_forwards > 0) {
debug("deferring postauth fork until remote forward "
"confirmation received");
} else
fork_postauth();
}
return client_loop(ssh, tty_flag, tty_flag ?
options.escape_char : SSH_ESCAPECHAR_NONE, id);
}
/* Loads all IdentityFile and CertificateFile keys */
static void
load_public_identity_files(struct passwd *pw)
{
char *filename, *cp;
struct sshkey *public;
int i;
u_int n_ids, n_certs;
char *identity_files[SSH_MAX_IDENTITY_FILES];
struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
int identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
char *certificate_files[SSH_MAX_CERTIFICATE_FILES];
struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES];
#ifdef ENABLE_PKCS11
struct sshkey **keys;
int nkeys;
#endif /* PKCS11 */
n_ids = n_certs = 0;
memset(identity_files, 0, sizeof(identity_files));
memset(identity_keys, 0, sizeof(identity_keys));
memset(identity_file_userprovided, 0,
sizeof(identity_file_userprovided));
memset(certificate_files, 0, sizeof(certificate_files));
memset(certificates, 0, sizeof(certificates));
memset(certificate_file_userprovided, 0,
sizeof(certificate_file_userprovided));
#ifdef ENABLE_PKCS11
if (options.pkcs11_provider != NULL &&
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
(pkcs11_init(!options.batch_mode) == 0) &&
(nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL,
&keys)) > 0) {
for (i = 0; i < nkeys; i++) {
if (n_ids >= SSH_MAX_IDENTITY_FILES) {
sshkey_free(keys[i]);
continue;
}
identity_keys[n_ids] = keys[i];
identity_files[n_ids] =
xstrdup(options.pkcs11_provider); /* XXX */
n_ids++;
}
free(keys);
}
#endif /* ENABLE_PKCS11 */
for (i = 0; i < options.num_identity_files; i++) {
if (n_ids >= SSH_MAX_IDENTITY_FILES ||
strcasecmp(options.identity_files[i], "none") == 0) {
free(options.identity_files[i]);
options.identity_files[i] = NULL;
continue;
}
cp = tilde_expand_filename(options.identity_files[i], getuid());
filename = percent_expand(cp, "d", pw->pw_dir,
"u", pw->pw_name, "l", thishost, "h", host,
"r", options.user, (char *)NULL);
free(cp);
check_load(sshkey_load_public(filename, &public, NULL),
filename, "pubkey");
debug("identity file %s type %d", filename,
public ? public->type : -1);
free(options.identity_files[i]);
identity_files[n_ids] = filename;
identity_keys[n_ids] = public;
identity_file_userprovided[n_ids] =
options.identity_file_userprovided[i];
if (++n_ids >= SSH_MAX_IDENTITY_FILES)
continue;
/*
* If no certificates have been explicitly listed then try
* to add the default certificate variant too.
*/
if (options.num_certificate_files != 0)
continue;
xasprintf(&cp, "%s-cert", filename);
check_load(sshkey_load_public(cp, &public, NULL),
filename, "pubkey");
debug("identity file %s type %d", cp,
public ? public->type : -1);
if (public == NULL) {
free(cp);
continue;
}
if (!sshkey_is_cert(public)) {
debug("%s: key %s type %s is not a certificate",
__func__, cp, sshkey_type(public));
sshkey_free(public);
free(cp);
continue;
}
/* NB. leave filename pointing to private key */
identity_files[n_ids] = xstrdup(filename);
identity_keys[n_ids] = public;
identity_file_userprovided[n_ids] =
options.identity_file_userprovided[i];
n_ids++;
}
if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES)
fatal("%s: too many certificates", __func__);
for (i = 0; i < options.num_certificate_files; i++) {
cp = tilde_expand_filename(options.certificate_files[i],
getuid());
filename = percent_expand(cp,
"d", pw->pw_dir,
"h", host,
"i", uidstr,
"l", thishost,
"r", options.user,
"u", pw->pw_name,
(char *)NULL);
free(cp);
check_load(sshkey_load_public(filename, &public, NULL),
filename, "certificate");
debug("certificate file %s type %d", filename,
public ? public->type : -1);
free(options.certificate_files[i]);
options.certificate_files[i] = NULL;
if (public == NULL) {
free(filename);
continue;
}
if (!sshkey_is_cert(public)) {
debug("%s: key %s type %s is not a certificate",
__func__, filename, sshkey_type(public));
sshkey_free(public);
free(filename);
continue;
}
certificate_files[n_certs] = filename;
certificates[n_certs] = public;
certificate_file_userprovided[n_certs] =
options.certificate_file_userprovided[i];
++n_certs;
}
options.num_identity_files = n_ids;
memcpy(options.identity_files, identity_files, sizeof(identity_files));
memcpy(options.identity_keys, identity_keys, sizeof(identity_keys));
memcpy(options.identity_file_userprovided,
identity_file_userprovided, sizeof(identity_file_userprovided));
options.num_certificate_files = n_certs;
memcpy(options.certificate_files,
certificate_files, sizeof(certificate_files));
memcpy(options.certificates, certificates, sizeof(certificates));
memcpy(options.certificate_file_userprovided,
certificate_file_userprovided,
sizeof(certificate_file_userprovided));
}
static void
main_sigchld_handler(int sig)
{
int save_errno = errno;
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
;
errno = save_errno;
}
diff --git a/ssh.h b/ssh.h
index 5abfd7a688fe..dda6f617e695 100644
--- a/ssh.h
+++ b/ssh.h
@@ -1,95 +1,99 @@
-/* $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>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
/* Cipher used for encrypting authentication files. */
#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
/* Default port number. */
#define SSH_DEFAULT_PORT 22
/*
* Maximum number of certificate files that can be specified
* in configuration files or on the command line.
*/
#define SSH_MAX_CERTIFICATE_FILES 100
/*
* Maximum number of RSA authentication identity files that can be specified
* in configuration files or on the command line.
*/
#define SSH_MAX_IDENTITY_FILES 100
/*
* Major protocol version. Different version indicates major incompatibility
* that prevents communication.
*
* Minor protocol version. Different version indicates minor incompatibility
* that does not prevent interoperation.
*/
#define PROTOCOL_MAJOR_1 1
#define PROTOCOL_MINOR_1 5
/* We support only SSH2 */
#define PROTOCOL_MAJOR_2 2
#define PROTOCOL_MINOR_2 0
/*
* Name for the service. The port named by this service overrides the
* default port if present.
*/
#define SSH_SERVICE_NAME "ssh"
/*
* Name of the environment variable containing the process ID of the
* authentication agent.
*/
#define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID"
/*
* Name of the environment variable containing the pathname of the
* authentication socket.
*/
#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
/*
* Environment variable for overwriting the default location of askpass
*/
#define SSH_ASKPASS_ENV "SSH_ASKPASS"
/*
* Force host key length and server key length to differ by at least this
* many bits. This is to make double encryption with rsaref work.
*/
#define SSH_KEY_BITS_RESERVED 128
/*
* Length of the session key in bytes. (Specified as 256 bits in the
* protocol.)
*/
#define SSH_SESSION_KEY_LENGTH 32
/* Used to identify ``EscapeChar none'' */
#define SSH_ESCAPECHAR_NONE -2
/*
* unprivileged user when UsePrivilegeSeparation=yes;
* sshd will change its privileges to this user and its
* primary group.
*/
#ifndef SSH_PRIVSEP_USER
#define SSH_PRIVSEP_USER "sshd"
#endif
/* Listen backlog for sshd, ssh-agent and forwarding sockets */
#define SSH_LISTEN_BACKLOG 128
+
+/* Limits for banner exchange */
+#define SSH_MAX_BANNER_LEN 8192
+#define SSH_MAX_PRE_BANNER_LINES 1024
diff --git a/ssh_api.c b/ssh_api.c
index c84b4e713bf4..57509973b510 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,540 +1,558 @@
-/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */
+/* $OpenBSD: ssh_api.c,v 1.15 2019/01/21 10:38:54 djm Exp $ */
/*
* Copyright (c) 2012 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include "ssh_api.h"
#include "compat.h"
#include "log.h"
#include "authfile.h"
#include "sshkey.h"
#include "misc.h"
#include "ssh2.h"
#include "version.h"
#include "myproposal.h"
#include "ssherr.h"
#include "sshbuf.h"
+#include "openbsd-compat/openssl-compat.h"
+
#include <string.h>
int _ssh_exchange_banner(struct ssh *);
-int _ssh_send_banner(struct ssh *, char **);
-int _ssh_read_banner(struct ssh *, char **);
+int _ssh_send_banner(struct ssh *, struct sshbuf *);
+int _ssh_read_banner(struct ssh *, struct sshbuf *);
int _ssh_order_hostkeyalgs(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_private_key(int, int, struct ssh *);
-int _ssh_host_key_sign(struct sshkey *, struct sshkey *,
- u_char **, size_t *, const u_char *, size_t, const char *, u_int);
+int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *,
+ u_char **, size_t *, const u_char *, size_t, const char *);
/*
* stubs for the server side implementation of kex.
* disable privsep so our stubs will never be called.
*/
int use_privsep = 0;
int mm_sshkey_sign(struct sshkey *, u_char **, u_int *,
u_char *, u_int, char *, u_int);
DH *mm_choose_dh(int, int, int);
/* Define these two variables here so that they are part of the library */
u_char *session_id2 = NULL;
u_int session_id2_len = 0;
int
mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
u_char *data, u_int datalen, char *alg, u_int compat)
{
return (-1);
}
DH *
mm_choose_dh(int min, int nbits, int max)
{
return (NULL);
}
/* API */
int
ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
{
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
struct ssh *ssh;
char **proposal;
static int called;
int r;
if (!called) {
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif /* WITH_OPENSSL */
+ seed_rng();
called = 1;
}
if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if (is_server)
ssh_packet_set_server(ssh);
/* Initialize key exchange */
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);
return r;
}
ssh->kex->server = is_server;
if (is_server) {
#ifdef WITH_OPENSSL
- ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
- ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server;
- ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server;
- ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server;
+ ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif /* WITH_OPENSSL */
- ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
ssh->kex->load_host_public_key=&_ssh_host_public_key;
ssh->kex->load_host_private_key=&_ssh_host_private_key;
ssh->kex->sign=&_ssh_host_key_sign;
} else {
#ifdef WITH_OPENSSL
- ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
- ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
- ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client;
- ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client;
- ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client;
+ ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
# ifdef OPENSSL_HAS_ECC
- ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+ ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
# endif
#endif /* WITH_OPENSSL */
- ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
+ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
ssh->kex->verify_host_key =&_ssh_verify_host_key;
}
*sshp = ssh;
return 0;
}
void
ssh_free(struct ssh *ssh)
{
struct key_entry *k;
ssh_packet_close(ssh);
/*
* we've only created the public keys variants in case we
* are a acting as a server.
*/
while ((k = TAILQ_FIRST(&ssh->public_keys)) != NULL) {
TAILQ_REMOVE(&ssh->public_keys, k, next);
if (ssh->kex && ssh->kex->server)
sshkey_free(k->key);
free(k);
}
while ((k = TAILQ_FIRST(&ssh->private_keys)) != NULL) {
TAILQ_REMOVE(&ssh->private_keys, k, next);
free(k);
}
if (ssh->kex)
kex_free(ssh->kex);
free(ssh);
}
void
ssh_set_app_data(struct ssh *ssh, void *app_data)
{
ssh->app_data = app_data;
}
void *
ssh_get_app_data(struct ssh *ssh)
{
return ssh->app_data;
}
/* Returns < 0 on error, 0 otherwise */
int
ssh_add_hostkey(struct ssh *ssh, struct sshkey *key)
{
struct sshkey *pubkey = NULL;
struct key_entry *k = NULL, *k_prv = NULL;
int r;
if (ssh->kex->server) {
if ((r = sshkey_from_private(key, &pubkey)) != 0)
return r;
if ((k = malloc(sizeof(*k))) == NULL ||
(k_prv = malloc(sizeof(*k_prv))) == NULL) {
free(k);
sshkey_free(pubkey);
return SSH_ERR_ALLOC_FAIL;
}
k_prv->key = key;
TAILQ_INSERT_TAIL(&ssh->private_keys, k_prv, next);
/* add the public key, too */
k->key = pubkey;
TAILQ_INSERT_TAIL(&ssh->public_keys, k, next);
r = 0;
} else {
if ((k = malloc(sizeof(*k))) == NULL)
return SSH_ERR_ALLOC_FAIL;
k->key = key;
TAILQ_INSERT_TAIL(&ssh->public_keys, k, next);
r = 0;
}
return r;
}
int
ssh_set_verify_host_key_callback(struct ssh *ssh,
int (*cb)(struct sshkey *, struct ssh *))
{
if (cb == NULL || ssh->kex == NULL)
return SSH_ERR_INVALID_ARGUMENT;
ssh->kex->verify_host_key = cb;
return 0;
}
int
ssh_input_append(struct ssh *ssh, const u_char *data, size_t len)
{
return sshbuf_put(ssh_packet_get_input(ssh), data, len);
}
int
ssh_packet_next(struct ssh *ssh, u_char *typep)
{
int r;
u_int32_t seqnr;
u_char type;
/*
* Try to read a packet. Return SSH_MSG_NONE if no packet or not
* enough data.
*/
*typep = SSH_MSG_NONE;
- if (ssh->kex->client_version_string == NULL ||
- ssh->kex->server_version_string == NULL)
+ if (sshbuf_len(ssh->kex->client_version) == 0 ||
+ sshbuf_len(ssh->kex->server_version) == 0)
return _ssh_exchange_banner(ssh);
/*
* If we enough data and a dispatch function then
* call the function and get the next packet.
* Otherwise return the packet type to the caller so it
* can decide how to go on.
*
* We will only call the dispatch function for:
* 20-29 Algorithm negotiation
* 30-49 Key exchange method specific (numbers can be reused for
* different authentication methods)
*/
for (;;) {
if ((r = ssh_packet_read_poll2(ssh, &type, &seqnr)) != 0)
return r;
if (type > 0 && type < DISPATCH_MAX &&
type >= SSH2_MSG_KEXINIT && type <= SSH2_MSG_TRANSPORT_MAX &&
ssh->dispatch[type] != NULL) {
if ((r = (*ssh->dispatch[type])(type, seqnr, ssh)) != 0)
return r;
} else {
*typep = type;
return 0;
}
}
}
const u_char *
ssh_packet_payload(struct ssh *ssh, size_t *lenp)
{
return sshpkt_ptr(ssh, lenp);
}
int
ssh_packet_put(struct ssh *ssh, int type, const u_char *data, size_t len)
{
int r;
if ((r = sshpkt_start(ssh, type)) != 0 ||
(r = sshpkt_put(ssh, data, len)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
return r;
return 0;
}
const u_char *
ssh_output_ptr(struct ssh *ssh, size_t *len)
{
struct sshbuf *output = ssh_packet_get_output(ssh);
*len = sshbuf_len(output);
return sshbuf_ptr(output);
}
int
ssh_output_consume(struct ssh *ssh, size_t len)
{
return sshbuf_consume(ssh_packet_get_output(ssh), len);
}
int
ssh_output_space(struct ssh *ssh, size_t len)
{
return (0 == sshbuf_check_reserve(ssh_packet_get_output(ssh), len));
}
int
ssh_input_space(struct ssh *ssh, size_t len)
{
return (0 == sshbuf_check_reserve(ssh_packet_get_input(ssh), len));
}
/* Read other side's version identification. */
int
-_ssh_read_banner(struct ssh *ssh, char **bannerp)
+_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
{
- struct sshbuf *input;
- const char *s;
- char buf[256], remote_version[256]; /* must be same size! */
+ struct sshbuf *input = ssh_packet_get_input(ssh);
const char *mismatch = "Protocol mismatch.\r\n";
- int r, remote_major, remote_minor;
- size_t i, n, j, len;
+ const u_char *s = sshbuf_ptr(input);
+ 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 (i = 0; i < sizeof(buf) - 1; i++) {
- if (j >= len)
- return (0);
- buf[i] = s[j++];
- if (buf[i] == '\r') {
- buf[i] = '\n';
- buf[i + 1] = 0;
- continue; /**XXX wait for \n */
+ sshbuf_reset(banner);
+ expect_nl = 0;
+ for (;;) {
+ if (j >= sshbuf_len(input))
+ return 0; /* insufficient data in input buf */
+ c = s[j++];
+ if (c == '\r') {
+ expect_nl = 1;
+ continue;
}
- if (buf[i] == '\n') {
- buf[i + 1] = 0;
+ if (c == '\n')
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 (strncmp(buf, "SSH-", 4) == 0)
+ if (sshbuf_len(banner) >= 4 &&
+ memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0)
break;
- debug("ssh_exchange_identification: %s", buf);
- if (ssh->kex->server || ++n > 65536) {
+ if ((cp = sshbuf_dup_string(banner)) == NULL)
+ 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),
mismatch, strlen(mismatch))) != 0)
return r;
return SSH_ERR_NO_PROTOCOL_VERSION;
}
}
if ((r = sshbuf_consume(input, j)) != 0)
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
* 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)
return SSH_ERR_INVALID_FORMAT;
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
ssh->compat = compat_datafellows(remote_version);
if (remote_major == 1 && remote_minor == 99) {
remote_major = 2;
remote_minor = 0;
}
if (remote_major != 2)
return SSH_ERR_PROTOCOL_MISMATCH;
- chop(buf);
- debug("Remote version string %.100s", buf);
- if ((*bannerp = strdup(buf)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
+ debug("Remote version string %.100s", cp);
+ free(cp);
return 0;
}
/* Send our own protocol version identification. */
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;
- snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION);
- if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0)
+ if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0)
+ return r;
+ if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0)
+ return r;
+ /* Remove trailing \r\n */
+ if ((r = sshbuf_consume_end(banner, 2)) != 0)
return r;
- chop(buf);
- debug("Local version string %.100s", buf);
- if ((*bannerp = strdup(buf)) == NULL)
+ if ((cp = sshbuf_dup_string(banner)) == NULL)
return SSH_ERR_ALLOC_FAIL;
+ debug("Local version string %.100s", cp);
+ free(cp);
return 0;
}
int
_ssh_exchange_banner(struct ssh *ssh)
{
struct kex *kex = ssh->kex;
int r;
/*
* if _ssh_read_banner() cannot parse a full version string
* it will return NULL and we end up calling it again.
*/
r = 0;
if (kex->server) {
- if (kex->server_version_string == NULL)
- r = _ssh_send_banner(ssh, &kex->server_version_string);
+ if (sshbuf_len(ssh->kex->server_version) == 0)
+ r = _ssh_send_banner(ssh, ssh->kex->server_version);
if (r == 0 &&
- kex->server_version_string != NULL &&
- kex->client_version_string == NULL)
- r = _ssh_read_banner(ssh, &kex->client_version_string);
+ sshbuf_len(ssh->kex->server_version) != 0 &&
+ sshbuf_len(ssh->kex->client_version) == 0)
+ r = _ssh_read_banner(ssh, ssh->kex->client_version);
} else {
- if (kex->server_version_string == NULL)
- r = _ssh_read_banner(ssh, &kex->server_version_string);
+ if (sshbuf_len(ssh->kex->server_version) == 0)
+ r = _ssh_read_banner(ssh, ssh->kex->server_version);
if (r == 0 &&
- kex->server_version_string != NULL &&
- kex->client_version_string == NULL)
- r = _ssh_send_banner(ssh, &kex->client_version_string);
+ sshbuf_len(ssh->kex->server_version) != 0 &&
+ sshbuf_len(ssh->kex->client_version) == 0)
+ r = _ssh_send_banner(ssh, ssh->kex->client_version);
}
if (r != 0)
return r;
/* start initial kex as soon as we have exchanged the banners */
- if (kex->server_version_string != NULL &&
- kex->client_version_string != NULL) {
+ if (sshbuf_len(ssh->kex->server_version) != 0 &&
+ sshbuf_len(ssh->kex->client_version) != 0) {
if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 ||
(r = kex_send_kexinit(ssh)) != 0)
return r;
}
return 0;
}
struct sshkey *
_ssh_host_public_key(int type, int nid, struct ssh *ssh)
{
struct key_entry *k;
debug3("%s: need %d", __func__, type);
TAILQ_FOREACH(k, &ssh->public_keys, next) {
debug3("%s: check %s", __func__, sshkey_type(k->key));
if (k->key->type == type &&
(type != KEY_ECDSA || k->key->ecdsa_nid == nid))
return (k->key);
}
return (NULL);
}
struct sshkey *
_ssh_host_private_key(int type, int nid, struct ssh *ssh)
{
struct key_entry *k;
debug3("%s: need %d", __func__, type);
TAILQ_FOREACH(k, &ssh->private_keys, next) {
debug3("%s: check %s", __func__, sshkey_type(k->key));
if (k->key->type == type &&
(type != KEY_ECDSA || k->key->ecdsa_nid == nid))
return (k->key);
}
return (NULL);
}
int
_ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh)
{
struct key_entry *k;
debug3("%s: need %s", __func__, sshkey_type(hostkey));
TAILQ_FOREACH(k, &ssh->public_keys, next) {
debug3("%s: check %s", __func__, sshkey_type(k->key));
if (sshkey_equal_public(hostkey, k->key))
return (0); /* ok */
}
return (-1); /* failed */
}
/* offer hostkey algorithms in kexinit depending on registered keys */
int
_ssh_order_hostkeyalgs(struct ssh *ssh)
{
struct key_entry *k;
char *orig, *avail, *oavail = NULL, *alg, *replace = NULL;
char **proposal;
size_t maxlen;
int ktype, r;
/* XXX we de-serialize ssh->kex->my, modify it, and change it */
if ((r = kex_buf2prop(ssh->kex->my, NULL, &proposal)) != 0)
return r;
orig = proposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
if ((oavail = avail = strdup(orig)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
maxlen = strlen(avail) + 1;
if ((replace = calloc(1, maxlen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
*replace = '\0';
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
continue;
TAILQ_FOREACH(k, &ssh->public_keys, next) {
if (k->key->type == ktype ||
(sshkey_is_cert(k->key) && k->key->type ==
sshkey_type_plain(ktype))) {
if (*replace != '\0')
strlcat(replace, ",", maxlen);
strlcat(replace, alg, maxlen);
break;
}
}
}
if (*replace != '\0') {
debug2("%s: orig/%d %s", __func__, ssh->kex->server, orig);
debug2("%s: replace/%d %s", __func__, ssh->kex->server, replace);
free(orig);
proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace;
replace = NULL; /* owned by proposal */
r = kex_prop2buf(ssh->kex->my, proposal);
}
out:
free(oavail);
free(replace);
kex_prop_free(proposal);
return r;
}
int
-_ssh_host_key_sign(struct sshkey *privkey, struct sshkey *pubkey,
- u_char **signature, size_t *slen, const u_char *data, size_t dlen,
- const char *alg, u_int compat)
+_ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey,
+ struct sshkey *pubkey, u_char **signature, size_t *slen,
+ const u_char *data, size_t dlen, const char *alg)
{
- return sshkey_sign(privkey, signature, slen, data, dlen, alg, compat);
+ return sshkey_sign(privkey, signature, slen, data, dlen,
+ alg, ssh->compat);
}
diff --git a/ssh_config b/ssh_config
index c12f5ef52f48..5e8ef548bb50 100644
--- a/ssh_config
+++ b/ssh_config
@@ -1,46 +1,45 @@
-# $OpenBSD: ssh_config,v 1.33 2017/05/07 23:12:57 djm Exp $
+# $OpenBSD: ssh_config,v 1.34 2019/02/04 02:39:42 dtucker Exp $
# This is the ssh client system-wide configuration file. See
# ssh_config(5) for more information. This file provides defaults for
# users, and the values can be changed in per-user configuration files
# or on the command line.
# Configuration data is parsed as follows:
# 1. command line options
# 2. user-specific file
# 3. system-wide file
# Any configuration value is only changed the first time it is set.
# Thus, host-specific definitions should be at the beginning of the
# configuration file, and defaults at the end.
# Site-wide defaults for some commonly used options. For a comprehensive
# list of available options, their meanings and defaults, please see the
# ssh_config(5) man page.
# Host *
# ForwardAgent no
# ForwardX11 no
# PasswordAuthentication yes
# HostbasedAuthentication no
# GSSAPIAuthentication no
# GSSAPIDelegateCredentials no
# BatchMode no
# CheckHostIP yes
# AddressFamily any
# ConnectTimeout 0
# StrictHostKeyChecking ask
# IdentityFile ~/.ssh/id_rsa
# IdentityFile ~/.ssh/id_dsa
# IdentityFile ~/.ssh/id_ecdsa
# IdentityFile ~/.ssh/id_ed25519
# Port 22
-# Protocol 2
# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
# MACs hmac-md5,hmac-sha1,umac-64@openssh.com
# EscapeChar ~
# Tunnel no
# TunnelDevice any:any
# PermitLocalCommand no
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
diff --git a/ssh_config.0 b/ssh_config.0
index eb7f929e6df9..10f1c2e9d373 100644
--- a/ssh_config.0
+++ b/ssh_config.0
@@ -1,1109 +1,1119 @@
SSH_CONFIG(5) File Formats Manual SSH_CONFIG(5)
NAME
ssh_config M-bM-^@M-^S OpenSSH SSH client configuration files
DESCRIPTION
ssh(1) obtains configuration data from the following sources in the
following order:
1. command-line options
2. user's configuration file (~/.ssh/config)
3. system-wide configuration file (/etc/ssh/ssh_config)
For each parameter, the first obtained value will be used. The
configuration files contain sections separated by Host specifications,
and that section is only applied for hosts that match one of the patterns
given in the specification. The matched host name is usually the one
given on the command line (see the CanonicalizeHostname option for
exceptions).
Since the first obtained value for each parameter is used, more host-
specific declarations should be given near the beginning of the file, and
general defaults at the end.
The file contains keyword-argument pairs, one per line. Lines starting
with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines are interpreted as comments. Arguments may
optionally be enclosed in double quotes (") in order to represent
arguments containing spaces. Configuration options may be separated by
whitespace or optional whitespace and exactly one M-bM-^@M-^X=M-bM-^@M-^Y; the latter format
is useful to avoid the need to quote whitespace when specifying
configuration options using the ssh, scp, and sftp -o option.
The possible keywords and their meanings are as follows (note that
keywords are case-insensitive and arguments are case-sensitive):
Host Restricts the following declarations (up to the next Host or
Match keyword) to be only for those hosts that match one of the
patterns given after the keyword. If more than one pattern is
provided, they should be separated by whitespace. A single M-bM-^@M-^X*M-bM-^@M-^Y
as a pattern can be used to provide global defaults for all
hosts. The host is usually the hostname argument given on the
command line (see the CanonicalizeHostname keyword for
exceptions).
A pattern entry may be negated by prefixing it with an
exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y). If a negated entry is matched, then the
Host entry is ignored, regardless of whether any other patterns
on the line match. Negated matches are therefore useful to
provide exceptions for wildcard matches.
See PATTERNS for more information on patterns.
Match Restricts the following declarations (up to the next Host or
Match keyword) to be used only when the conditions following the
Match keyword are satisfied. Match conditions are specified
using one or more criteria or the single token all which always
- matches. The available criteria keywords are: canonical, exec,
- host, originalhost, user, and localuser. The all criteria must
- appear alone or immediately after canonical. Other criteria may
- be combined arbitrarily. All criteria but all and canonical
- require an argument. Criteria may be negated by prepending an
- exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y).
+ matches. The available criteria keywords are: canonical, final,
+ exec, host, originalhost, user, and localuser. The all criteria
+ must appear alone or immediately after canonical or final. Other
+ criteria may be combined arbitrarily. All criteria but all,
+ canonical, and final require an argument. Criteria may be
+ negated by prepending an exclamation mark (M-bM-^@M-^X!M-bM-^@M-^Y).
The canonical keyword matches only when the configuration file is
being re-parsed after hostname canonicalization (see the
- CanonicalizeHostname option.) This may be useful to specify
- conditions that work with canonical host names only. The exec
- keyword executes the specified command under the user's shell.
- If the command returns a zero exit status then the condition is
- considered true. Commands containing whitespace characters must
- be quoted. Arguments to exec accept the tokens described in the
- TOKENS section.
+ CanonicalizeHostname option). This may be useful to specify
+ conditions that work with canonical host names only.
+
+ The final keyword requests that the configuration be re-parsed
+ (regardless of whether CanonicalizeHostname is enabled), and
+ matches only during this final pass. If CanonicalizeHostname is
+ enabled, then canonical and final match during the same pass.
+
+ The exec keyword executes the specified command under the user's
+ shell. If the command returns a zero exit status then the
+ condition is considered true. Commands containing whitespace
+ characters must be quoted. Arguments to exec accept the tokens
+ described in the TOKENS section.
The other keywords' criteria must be single entries or comma-
separated lists and may use the wildcard and negation operators
described in the PATTERNS section. The criteria for the host
keyword are matched against the target hostname, after any
substitution by the Hostname or CanonicalizeHostname options.
The originalhost keyword matches against the hostname as it was
specified on the command-line. The user keyword matches against
the target username on the remote host. The localuser keyword
matches against the name of the local user running ssh(1) (this
keyword may be useful in system-wide ssh_config files).
AddKeysToAgent
Specifies whether keys should be automatically added to a running
ssh-agent(1). If this option is set to yes and a key is loaded
from a file, the key and its passphrase are added to the agent
with the default lifetime, as if by ssh-add(1). If this option
is set to ask, ssh(1) will require confirmation using the
SSH_ASKPASS program before adding a key (see ssh-add(1) for
details). If this option is set to confirm, each use of the key
must be confirmed, as if the -c option was specified to
ssh-add(1). If this option is set to no, no keys are added to
the agent. The argument must be yes, confirm, ask, or no (the
default).
AddressFamily
Specifies which address family to use when connecting. Valid
arguments are any (the default), inet (use IPv4 only), or inet6
(use IPv6 only).
BatchMode
If set to yes, passphrase/password querying will be disabled.
This option is useful in scripts and other batch jobs where no
user is present to supply the password. The argument must be yes
or no (the default).
BindAddress
Use the specified address on the local machine as the source
address of the connection. Only useful on systems with more than
one address.
BindInterface
Use the address of the specified interface on the local machine
as the source address of the connection.
CanonicalDomains
When CanonicalizeHostname is enabled, this option specifies the
list of domain suffixes in which to search for the specified
destination host.
CanonicalizeFallbackLocal
Specifies whether to fail with an error when hostname
canonicalization fails. The default, yes, will attempt to look
up the unqualified hostname using the system resolver's search
rules. A value of no will cause ssh(1) to fail instantly if
CanonicalizeHostname is enabled and the target hostname cannot be
found in any of the domains specified by CanonicalDomains.
CanonicalizeHostname
Controls whether explicit hostname canonicalization is performed.
The default, no, is not to perform any name rewriting and let the
system resolver handle all hostname lookups. If set to yes then,
for connections that do not use a ProxyCommand or ProxyJump,
ssh(1) will attempt to canonicalize the hostname specified on the
command line using the CanonicalDomains suffixes and
CanonicalizePermittedCNAMEs rules. If CanonicalizeHostname is
set to always, then canonicalization is applied to proxied
connections too.
If this option is enabled, then the configuration files are
processed again using the new target name to pick up any new
configuration in matching Host and Match stanzas.
CanonicalizeMaxDots
Specifies the maximum number of dot characters in a hostname
before canonicalization is disabled. The default, 1, allows a
single dot (i.e. hostname.subdomain).
CanonicalizePermittedCNAMEs
Specifies rules to determine whether CNAMEs should be followed
when canonicalizing hostnames. The rules consist of one or more
arguments of source_domain_list:target_domain_list, where
source_domain_list is a pattern-list of domains that may follow
CNAMEs in canonicalization, and target_domain_list is a pattern-
list of domains that they may resolve to.
For example, "*.a.example.com:*.b.example.com,*.c.example.com"
will allow hostnames matching "*.a.example.com" to be
canonicalized to names in the "*.b.example.com" or
"*.c.example.com" domains.
CASignatureAlgorithms
Specifies which algorithms are allowed for signing of
certificates by certificate authorities (CAs). The default is:
ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
ssh(1) will not accept host certificates signed using algorithms
other than those specified.
CertificateFile
Specifies a file from which the user's certificate is read. A
corresponding private key must be provided separately in order to
use this certificate either from an IdentityFile directive or -i
flag to ssh(1), via ssh-agent(1), or via a PKCS11Provider.
Arguments to CertificateFile may use the tilde syntax to refer to
a user's home directory or the tokens described in the TOKENS
section.
It is possible to have multiple certificate files specified in
configuration files; these certificates will be tried in
sequence. Multiple CertificateFile directives will add to the
list of certificates used for authentication.
ChallengeResponseAuthentication
Specifies whether to use challenge-response authentication. The
argument to this keyword must be yes (the default) or no.
CheckHostIP
If set to yes (the default), ssh(1) will additionally check the
host IP address in the known_hosts file. This allows it to
detect if a host key changed due to DNS spoofing and will add
addresses of destination hosts to ~/.ssh/known_hosts in the
process, regardless of the setting of StrictHostKeyChecking. If
the option is set to no, the check will not be executed.
Ciphers
Specifies the ciphers allowed and their order of preference.
Multiple ciphers must be comma-separated. If the specified value
begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified ciphers will be
appended to the default set instead of replacing them. If the
specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified
ciphers (including wildcards) will be removed from the default
set instead of replacing them.
The supported ciphers are:
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
The default is:
chacha20-poly1305@openssh.com,
aes128-ctr,aes192-ctr,aes256-ctr,
aes128-gcm@openssh.com,aes256-gcm@openssh.com
The list of available ciphers may also be obtained using "ssh -Q
cipher".
ClearAllForwardings
Specifies that all local, remote, and dynamic port forwardings
specified in the configuration files or on the command line be
cleared. This option is primarily useful when used from the
ssh(1) command line to clear port forwardings set in
configuration files, and is automatically set by scp(1) and
sftp(1). The argument must be yes or no (the default).
Compression
Specifies whether to use compression. The argument must be yes
or no (the default).
ConnectionAttempts
Specifies the number of tries (one per second) to make before
exiting. The argument must be an integer. This may be useful in
scripts if the connection sometimes fails. The default is 1.
ConnectTimeout
Specifies the timeout (in seconds) used when connecting to the
SSH server, instead of using the default system TCP timeout.
This value is used only when the target is down or really
unreachable, not when it refuses the connection.
ControlMaster
Enables the sharing of multiple sessions over a single network
connection. When set to yes, ssh(1) will listen for connections
on a control socket specified using the ControlPath argument.
Additional sessions can connect to this socket using the same
ControlPath with ControlMaster set to no (the default). These
sessions will try to reuse the master instance's network
connection rather than initiating new ones, but will fall back to
connecting normally if the control socket does not exist, or is
not listening.
Setting this to ask will cause ssh(1) to listen for control
connections, but require confirmation using ssh-askpass(1). If
the ControlPath cannot be opened, ssh(1) will continue without
connecting to a master instance.
X11 and ssh-agent(1) forwarding is supported over these
multiplexed connections, however the display and agent forwarded
will be the one belonging to the master connection i.e. it is not
possible to forward multiple displays or agents.
Two additional options allow for opportunistic multiplexing: try
to use a master connection but fall back to creating a new one if
one does not already exist. These options are: auto and autoask.
The latter requires confirmation like the ask option.
ControlPath
Specify the path to the control socket used for connection
sharing as described in the ControlMaster section above or the
string none to disable connection sharing. Arguments to
ControlPath may use the tilde syntax to refer to a user's home
directory or the tokens described in the TOKENS section. It is
recommended that any ControlPath used for opportunistic
connection sharing include at least %h, %p, and %r (or
alternatively %C) and be placed in a directory that is not
writable by other users. This ensures that shared connections
are uniquely identified.
ControlPersist
When used in conjunction with ControlMaster, specifies that the
master connection should remain open in the background (waiting
for future client connections) after the initial client
connection has been closed. If set to no, then the master
connection will not be placed into the background, and will close
as soon as the initial client connection is closed. If set to
yes or 0, then the master connection will remain in the
background indefinitely (until killed or closed via a mechanism
such as the "ssh -O exit"). If set to a time in seconds, or a
time in any of the formats documented in sshd_config(5), then the
backgrounded master connection will automatically terminate after
it has remained idle (with no client connections) for the
specified time.
DynamicForward
Specifies that a TCP port on the local machine be forwarded over
the secure channel, and the application protocol is then used to
determine where to connect to from the remote machine.
The argument must be [bind_address:]port. IPv6 addresses can be
specified by enclosing addresses in square brackets. By default,
the local port is bound in accordance with the GatewayPorts
setting. However, an explicit bind_address may be used to bind
the connection to a specific address. The bind_address of
localhost indicates that the listening port be bound for local
use only, while an empty address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port
should be available from all interfaces.
Currently the SOCKS4 and SOCKS5 protocols are supported, and
ssh(1) will act as a SOCKS server. Multiple forwardings may be
specified, and additional forwardings can be given on the command
line. Only the superuser can forward privileged ports.
EnableSSHKeysign
Setting this option to yes in the global client configuration
file /etc/ssh/ssh_config enables the use of the helper program
ssh-keysign(8) during HostbasedAuthentication. The argument must
be yes or no (the default). This option should be placed in the
non-hostspecific section. See ssh-keysign(8) for more
information.
EscapeChar
Sets the escape character (default: M-bM-^@M-^X~M-bM-^@M-^Y). The escape character
can also be set on the command line. The argument should be a
single character, M-bM-^@M-^X^M-bM-^@M-^Y followed by a letter, or none to disable
the escape character entirely (making the connection transparent
for binary data).
ExitOnForwardFailure
Specifies whether ssh(1) should terminate the connection if it
cannot set up all requested dynamic, tunnel, local, and remote
port forwardings, (e.g. if either end is unable to bind and
listen on a specified port). Note that ExitOnForwardFailure does
not apply to connections made over port forwardings and will not,
for example, cause ssh(1) to exit if TCP connections to the
ultimate forwarding destination fail. The argument must be yes
or no (the default).
FingerprintHash
Specifies the hash algorithm used when displaying key
fingerprints. Valid options are: md5 and sha256 (the default).
ForwardAgent
Specifies whether the connection to the authentication agent (if
any) will be forwarded to the remote machine. The argument must
be yes or no (the default).
Agent forwarding should be enabled with caution. Users with the
ability to bypass file permissions on the remote host (for the
agent's Unix-domain socket) can access the local agent through
the forwarded connection. An attacker cannot obtain key material
from the agent, however they can perform operations on the keys
that enable them to authenticate using the identities loaded into
the agent.
ForwardX11
Specifies whether X11 connections will be automatically
redirected over the secure channel and DISPLAY set. The argument
must be yes or no (the default).
X11 forwarding should be enabled with caution. Users with the
ability to bypass file permissions on the remote host (for the
user's X11 authorization database) can access the local X11
display through the forwarded connection. An attacker may then
be able to perform activities such as keystroke monitoring if the
ForwardX11Trusted option is also enabled.
ForwardX11Timeout
Specify a timeout for untrusted X11 forwarding using the format
described in the TIME FORMATS section of sshd_config(5). X11
connections received by ssh(1) after this time will be refused.
Setting ForwardX11Timeout to zero will disable the timeout and
permit X11 forwarding for the life of the connection. The
default is to disable untrusted X11 forwarding after twenty
minutes has elapsed.
ForwardX11Trusted
If this option is set to yes, remote X11 clients will have full
access to the original X11 display.
If this option is set to no (the default), remote X11 clients
will be considered untrusted and prevented from stealing or
tampering with data belonging to trusted X11 clients.
Furthermore, the xauth(1) token used for the session will be set
to expire after 20 minutes. Remote clients will be refused
access after this time.
See the X11 SECURITY extension specification for full details on
the restrictions imposed on untrusted clients.
GatewayPorts
Specifies whether remote hosts are allowed to connect to local
forwarded ports. By default, ssh(1) binds local port forwardings
to the loopback address. This prevents other remote hosts from
connecting to forwarded ports. GatewayPorts can be used to
specify that ssh should bind local port forwardings to the
wildcard address, thus allowing remote hosts to connect to
forwarded ports. The argument must be yes or no (the default).
GlobalKnownHostsFile
Specifies one or more files to use for the global host key
database, separated by whitespace. The default is
/etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2.
GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is no.
GSSAPIDelegateCredentials
Forward (delegate) credentials to the server. The default is no.
HashKnownHosts
Indicates that ssh(1) should hash host names and addresses when
they are added to ~/.ssh/known_hosts. These hashed names may be
used normally by ssh(1) and sshd(8), but they do not reveal
identifying information should the file's contents be disclosed.
The default is no. Note that existing names and addresses in
known hosts files will not be converted automatically, but may be
manually hashed using ssh-keygen(1).
HostbasedAuthentication
Specifies whether to try rhosts based authentication with public
key authentication. The argument must be yes or no (the
default).
HostbasedKeyTypes
Specifies the key types that will be used for hostbased
authentication as a comma-separated list of patterns.
Alternately if the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character,
then the specified key types will be appended to the default set
instead of replacing them. If the specified value begins with a
M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified key types (including wildcards)
will be removed from the default set instead of replacing them.
The default for this option is:
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
The -Q option of ssh(1) may be used to list supported key types.
HostKeyAlgorithms
Specifies the host key algorithms that the client wants to use in
order of preference. Alternately if the specified value begins
with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified key types will be
appended to the default set instead of replacing them. If the
specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified
key types (including wildcards) will be removed from the default
set instead of replacing them. The default for this option is:
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
If hostkeys are known for the destination host then this default
is modified to prefer their algorithms.
The list of available key types may also be obtained using "ssh
-Q key".
HostKeyAlias
Specifies an alias that should be used instead of the real host
name when looking up or saving the host key in the host key
database files and when validating host certificates. This
option is useful for tunneling SSH connections or for multiple
servers running on a single host.
HostName
Specifies the real host name to log into. This can be used to
specify nicknames or abbreviations for hosts. Arguments to
HostName accept the tokens described in the TOKENS section.
Numeric IP addresses are also permitted (both on the command line
and in HostName specifications). The default is the name given
on the command line.
IdentitiesOnly
Specifies that ssh(1) should only use the authentication identity
and certificate files explicitly configured in the ssh_config
files or passed on the ssh(1) command-line, even if ssh-agent(1)
or a PKCS11Provider offers more identities. The argument to this
keyword must be yes or no (the default). This option is intended
for situations where ssh-agent offers many different identities.
IdentityAgent
Specifies the UNIX-domain socket used to communicate with the
authentication agent.
This option overrides the SSH_AUTH_SOCK environment variable and
can be used to select a specific agent. Setting the socket name
to none disables the use of an authentication agent. If the
string "SSH_AUTH_SOCK" is specified, the location of the socket
will be read from the SSH_AUTH_SOCK environment variable.
Otherwise if the specified value begins with a M-bM-^@M-^X$M-bM-^@M-^Y character,
then it will be treated as an environment variable containing the
location of the socket.
Arguments to IdentityAgent may use the tilde syntax to refer to a
user's home directory or the tokens described in the TOKENS
section.
IdentityFile
Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA
authentication identity is read. The default is ~/.ssh/id_dsa,
~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and ~/.ssh/id_rsa.
Additionally, any identities represented by the authentication
agent will be used for authentication unless IdentitiesOnly is
set. If no certificates have been explicitly specified by
CertificateFile, ssh(1) will try to load certificate information
from the filename obtained by appending -cert.pub to the path of
a specified IdentityFile.
Arguments to IdentityFile may use the tilde syntax to refer to a
user's home directory or the tokens described in the TOKENS
section.
It is possible to have multiple identity files specified in
configuration files; all these identities will be tried in
sequence. Multiple IdentityFile directives will add to the list
of identities tried (this behaviour differs from that of other
configuration directives).
IdentityFile may be used in conjunction with IdentitiesOnly to
select which identities in an agent are offered during
authentication. IdentityFile may also be used in conjunction
with CertificateFile in order to provide any certificate also
needed for authentication with the identity.
IgnoreUnknown
Specifies a pattern-list of unknown options to be ignored if they
are encountered in configuration parsing. This may be used to
suppress errors if ssh_config contains options that are
unrecognised by ssh(1). It is recommended that IgnoreUnknown be
listed early in the configuration file as it will not be applied
to unknown options that appear before it.
Include
Include the specified configuration file(s). Multiple pathnames
may be specified and each pathname may contain glob(7) wildcards
and, for user configurations, shell-like M-bM-^@M-^X~M-bM-^@M-^Y references to user
home directories. Files without absolute paths are assumed to be
in ~/.ssh if included in a user configuration file or /etc/ssh if
included from the system configuration file. Include directive
may appear inside a Match or Host block to perform conditional
inclusion.
IPQoS Specifies the IPv4 type-of-service or DSCP class for connections.
Accepted values are af11, af12, af13, af21, af22, af23, af31,
af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6,
cs7, ef, lowdelay, throughput, reliability, a numeric value, or
none to use the operating system default. This option may take
one or two arguments, separated by whitespace. If one argument
is specified, it is used as the packet class unconditionally. If
two values are specified, the first is automatically selected for
interactive sessions and the second for non-interactive sessions.
The default is af21 (Low-Latency Data) for interactive sessions
and cs1 (Lower Effort) for non-interactive sessions.
KbdInteractiveAuthentication
Specifies whether to use keyboard-interactive authentication.
The argument to this keyword must be yes (the default) or no.
KbdInteractiveDevices
Specifies the list of methods to use in keyboard-interactive
authentication. Multiple method names must be comma-separated.
The default is to use the server specified list. The methods
available vary depending on what the server supports. For an
OpenSSH server, it may be zero or more of: bsdauth and pam.
KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms. Multiple
algorithms must be comma-separated. Alternately if the specified
value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified methods
will be appended to the default set instead of replacing them.
If the specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the
specified methods (including wildcards) will be removed from the
default set instead of replacing them. The default is:
curve25519-sha256,curve25519-sha256@libssh.org,
ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
diffie-hellman-group-exchange-sha256,
diffie-hellman-group16-sha512,
diffie-hellman-group18-sha512,
- diffie-hellman-group-exchange-sha1,
diffie-hellman-group14-sha256,
diffie-hellman-group14-sha1
The list of available key exchange algorithms may also be
obtained using "ssh -Q kex".
LocalCommand
Specifies a command to execute on the local machine after
successfully connecting to the server. The command string
extends to the end of the line, and is executed with the user's
shell. Arguments to LocalCommand accept the tokens described in
the TOKENS section.
The command is run synchronously and does not have access to the
session of the ssh(1) that spawned it. It should not be used for
interactive commands.
This directive is ignored unless PermitLocalCommand has been
enabled.
LocalForward
Specifies that a TCP port on the local machine be forwarded over
the secure channel to the specified host and port from the remote
machine. The first argument must be [bind_address:]port and the
second argument must be host:hostport. IPv6 addresses can be
specified by enclosing addresses in square brackets. Multiple
forwardings may be specified, and additional forwardings can be
given on the command line. Only the superuser can forward
privileged ports. By default, the local port is bound in
accordance with the GatewayPorts setting. However, an explicit
bind_address may be used to bind the connection to a specific
address. The bind_address of localhost indicates that the
listening port be bound for local use only, while an empty
address or M-bM-^@M-^X*M-bM-^@M-^Y indicates that the port should be available from
all interfaces.
LogLevel
Gives the verbosity level that is used when logging messages from
ssh(1). The possible values are: QUIET, FATAL, ERROR, INFO,
VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO.
DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify
higher levels of verbose output.
MACs Specifies the MAC (message authentication code) algorithms in
order of preference. The MAC algorithm is used for data
integrity protection. Multiple algorithms must be comma-
separated. If the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character,
then the specified algorithms will be appended to the default set
instead of replacing them. If the specified value begins with a
M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified algorithms (including
wildcards) will be removed from the default set instead of
replacing them.
The algorithms that contain "-etm" calculate the MAC after
encryption (encrypt-then-mac). These are considered safer and
their use recommended.
The default is:
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
hmac-sha1-etm@openssh.com,
umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-sha1
The list of available MAC algorithms may also be obtained using
"ssh -Q mac".
NoHostAuthenticationForLocalhost
Disable host authentication for localhost (loopback addresses).
The argument to this keyword must be yes or no (the default).
NumberOfPasswordPrompts
Specifies the number of password prompts before giving up. The
argument to this keyword must be an integer. The default is 3.
PasswordAuthentication
Specifies whether to use password authentication. The argument
to this keyword must be yes (the default) or no.
PermitLocalCommand
Allow local command execution via the LocalCommand option or
using the !command escape sequence in ssh(1). The argument must
be yes or no (the default).
PKCS11Provider
- Specifies which PKCS#11 provider to use. The argument to this
- keyword is the PKCS#11 shared library ssh(1) should use to
- communicate with a PKCS#11 token providing the user's private RSA
- key.
+ Specifies which PKCS#11 provider to use or none to indicate that
+ no provider should be used (the default). The argument to this
+ keyword is a path to the PKCS#11 shared library ssh(1) should use
+ to communicate with a PKCS#11 token providing keys for user
+ authentication.
Port Specifies the port number to connect on the remote host. The
default is 22.
PreferredAuthentications
Specifies the order in which the client should try authentication
methods. This allows a client to prefer one method (e.g.
keyboard-interactive) over another method (e.g. password). The
default is:
gssapi-with-mic,hostbased,publickey,
keyboard-interactive,password
ProxyCommand
Specifies the command to use to connect to the server. The
command string extends to the end of the line, and is executed
using the user's shell M-bM-^@M-^XexecM-bM-^@M-^Y directive to avoid a lingering
shell process.
Arguments to ProxyCommand accept the tokens described in the
TOKENS section. The command can be basically anything, and
should read from its standard input and write to its standard
output. It should eventually connect an sshd(8) server running
on some machine, or execute sshd -i somewhere. Host key
management will be done using the HostName of the host being
connected (defaulting to the name typed by the user). Setting
the command to none disables this option entirely. Note that
CheckHostIP is not available for connects with a proxy command.
This directive is useful in conjunction with nc(1) and its proxy
support. For example, the following directive would connect via
an HTTP proxy at 192.0.2.0:
ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
ProxyJump
Specifies one or more jump proxies as either [user@]host[:port]
or an ssh URI. Multiple proxies may be separated by comma
characters and will be visited sequentially. Setting this option
will cause ssh(1) to connect to the target host by first making a
ssh(1) connection to the specified ProxyJump host and then
establishing a TCP forwarding to the ultimate target from there.
Note that this option will compete with the ProxyCommand option -
whichever is specified first will prevent later instances of the
other from taking effect.
+ Note also that the configuration for the destination host (either
+ supplied via the command-line or the configuration file) is not
+ generally applied to jump hosts. ~/.ssh/config should be used if
+ specific configuration is required for jump hosts.
+
ProxyUseFdpass
Specifies that ProxyCommand will pass a connected file descriptor
back to ssh(1) instead of continuing to execute and pass data.
The default is no.
PubkeyAcceptedKeyTypes
Specifies the key types that will be used for public key
authentication as a comma-separated list of patterns.
Alternately if the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character,
then the key types after it will be appended to the default
instead of replacing it. If the specified value begins with a
M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified key types (including wildcards)
will be removed from the default set instead of replacing them.
The default for this option is:
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
The list of available key types may also be obtained using "ssh
-Q key".
PubkeyAuthentication
Specifies whether to try public key authentication. The argument
to this keyword must be yes (the default) or no.
RekeyLimit
Specifies the maximum amount of data that may be transmitted
before the session key is renegotiated, optionally followed a
maximum amount of time that may pass before the session key is
renegotiated. The first argument is specified in bytes and may
have a suffix of M-bM-^@M-^XKM-bM-^@M-^Y, M-bM-^@M-^XMM-bM-^@M-^Y, or M-bM-^@M-^XGM-bM-^@M-^Y to indicate Kilobytes,
Megabytes, or Gigabytes, respectively. The default is between
M-bM-^@M-^X1GM-bM-^@M-^Y and M-bM-^@M-^X4GM-bM-^@M-^Y, depending on the cipher. The optional second
value is specified in seconds and may use any of the units
documented in the TIME FORMATS section of sshd_config(5). The
default value for RekeyLimit is default none, which means that
rekeying is performed after the cipher's default amount of data
has been sent or received and no time based rekeying is done.
RemoteCommand
Specifies a command to execute on the remote machine after
successfully connecting to the server. The command string
extends to the end of the line, and is executed with the user's
shell. Arguments to RemoteCommand accept the tokens described in
the TOKENS section.
RemoteForward
Specifies that a TCP port on the remote machine be forwarded over
the secure channel. The remote port may either be forwarded to a
specified host and port from the local machine, or may act as a
SOCKS 4/5 proxy that allows a remote client to connect to
arbitrary destinations from the local machine. The first
argument must be [bind_address:]port If forwarding to a specific
destination then the second argument must be host:hostport,
otherwise if no destination argument is specified then the remote
forwarding will be established as a SOCKS proxy.
IPv6 addresses can be specified by enclosing addresses in square
brackets. Multiple forwardings may be specified, and additional
forwardings can be given on the command line. Privileged ports
can be forwarded only when logging in as root on the remote
machine.
If the port argument is 0, the listen port will be dynamically
allocated on the server and reported to the client at run time.
If the bind_address is not specified, the default is to only bind
to loopback addresses. If the bind_address is M-bM-^@M-^X*M-bM-^@M-^Y or an empty
string, then the forwarding is requested to listen on all
interfaces. Specifying a remote bind_address will only succeed
if the server's GatewayPorts option is enabled (see
sshd_config(5)).
RequestTTY
Specifies whether to request a pseudo-tty for the session. The
argument may be one of: no (never request a TTY), yes (always
request a TTY when standard input is a TTY), force (always
request a TTY) or auto (request a TTY when opening a login
session). This option mirrors the -t and -T flags for ssh(1).
RevokedHostKeys
Specifies revoked host public keys. Keys listed in this file
will be refused for host authentication. Note that if this file
does not exist or is not readable, then host authentication will
be refused for all hosts. Keys may be specified as a text file,
listing one public key per line, or as an OpenSSH Key Revocation
List (KRL) as generated by ssh-keygen(1). For more information
on KRLs, see the KEY REVOCATION LISTS section in ssh-keygen(1).
SendEnv
Specifies what variables from the local environ(7) should be sent
to the server. The server must also support it, and the server
must be configured to accept these environment variables. Note
that the TERM environment variable is always sent whenever a
pseudo-terminal is requested as it is required by the protocol.
Refer to AcceptEnv in sshd_config(5) for how to configure the
server. Variables are specified by name, which may contain
wildcard characters. Multiple environment variables may be
separated by whitespace or spread across multiple SendEnv
directives.
See PATTERNS for more information on patterns.
It is possible to clear previously set SendEnv variable names by
prefixing patterns with -. The default is not to send any
environment variables.
ServerAliveCountMax
Sets the number of server alive messages (see below) which may be
sent without ssh(1) receiving any messages back from the server.
If this threshold is reached while server alive messages are
being sent, ssh will disconnect from the server, terminating the
session. It is important to note that the use of server alive
messages is very different from TCPKeepAlive (below). The server
alive messages are sent through the encrypted channel and
therefore will not be spoofable. The TCP keepalive option
enabled by TCPKeepAlive is spoofable. The server alive mechanism
is valuable when the client or server depend on knowing when a
connection has become inactive.
The default value is 3. If, for example, ServerAliveInterval
(see below) is set to 15 and ServerAliveCountMax is left at the
default, if the server becomes unresponsive, ssh will disconnect
after approximately 45 seconds.
ServerAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the server, ssh(1) will send a message through
the encrypted channel to request a response from the server. The
default is 0, indicating that these messages will not be sent to
the server.
SetEnv Directly specify one or more environment variables and their
contents to be sent to the server. Similarly to SendEnv, the
server must be prepared to accept the environment variable.
StreamLocalBindMask
Sets the octal file creation mode mask (umask) used when creating
a Unix-domain socket file for local or remote port forwarding.
This option is only used for port forwarding to a Unix-domain
socket file.
The default value is 0177, which creates a Unix-domain socket
file that is readable and writable only by the owner. Note that
not all operating systems honor the file mode on Unix-domain
socket files.
StreamLocalBindUnlink
Specifies whether to remove an existing Unix-domain socket file
for local or remote port forwarding before creating a new one.
If the socket file already exists and StreamLocalBindUnlink is
not enabled, ssh will be unable to forward the port to the Unix-
domain socket file. This option is only used for port forwarding
to a Unix-domain socket file.
The argument must be yes or no (the default).
StrictHostKeyChecking
If this flag is set to yes, ssh(1) will never automatically add
host keys to the ~/.ssh/known_hosts file, and refuses to connect
to hosts whose host key has changed. This provides maximum
protection against man-in-the-middle (MITM) attacks, though it
can be annoying when the /etc/ssh/ssh_known_hosts file is poorly
maintained or when connections to new hosts are frequently made.
This option forces the user to manually add all new hosts.
If this flag is set to M-bM-^@M-^\accept-newM-bM-^@M-^] then ssh will automatically
add new host keys to the user known hosts files, but will not
permit connections to hosts with changed host keys. If this flag
is set to M-bM-^@M-^\noM-bM-^@M-^] or M-bM-^@M-^\offM-bM-^@M-^], ssh will automatically add new host keys
to the user known hosts files and allow connections to hosts with
changed hostkeys to proceed, subject to some restrictions. If
this flag is set to ask (the default), new host keys will be
added to the user known host files only after the user has
confirmed that is what they really want to do, and ssh will
refuse to connect to hosts whose host key has changed. The host
keys of known hosts will be verified automatically in all cases.
SyslogFacility
Gives the facility code that is used when logging messages from
ssh(1). The possible values are: DAEMON, USER, AUTH, LOCAL0,
LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
default is USER.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
to the other side. If they are sent, death of the connection or
crash of one of the machines will be properly noticed. However,
this means that connections will die if the route is down
temporarily, and some people find it annoying.
The default is yes (to send TCP keepalive messages), and the
client will notice if the network goes down or the remote host
dies. This is important in scripts, and many users want it too.
To disable TCP keepalive messages, the value should be set to no.
See also ServerAliveInterval for protocol-level keepalives.
Tunnel Request tun(4) device forwarding between the client and the
server. The argument must be yes, point-to-point (layer 3),
ethernet (layer 2), or no (the default). Specifying yes requests
the default tunnel mode, which is point-to-point.
TunnelDevice
Specifies the tun(4) devices to open on the client (local_tun)
and the server (remote_tun).
The argument must be local_tun[:remote_tun]. The devices may be
specified by numerical ID or the keyword any, which uses the next
available tunnel device. If remote_tun is not specified, it
defaults to any. The default is any:any.
UpdateHostKeys
Specifies whether ssh(1) should accept notifications of
additional hostkeys from the server sent after authentication has
completed and add them to UserKnownHostsFile. The argument must
be yes, no (the default) or ask. Enabling this option allows
learning alternate hostkeys for a server and supports graceful
key rotation by allowing a server to send replacement public keys
before old ones are removed. Additional hostkeys are only
accepted if the key used to authenticate the host was already
trusted or explicitly accepted by the user. If UpdateHostKeys is
set to ask, then the user is asked to confirm the modifications
to the known_hosts file. Confirmation is currently incompatible
with ControlPersist, and will be disabled if it is enabled.
Presently, only sshd(8) from OpenSSH 6.8 and greater support the
"hostkeys@openssh.com" protocol extension used to inform the
client of all the server's hostkeys.
User Specifies the user to log in as. This can be useful when a
different user name is used on different machines. This saves
the trouble of having to remember to give the user name on the
command line.
UserKnownHostsFile
Specifies one or more files to use for the user host key
database, separated by whitespace. The default is
~/.ssh/known_hosts, ~/.ssh/known_hosts2.
VerifyHostKeyDNS
Specifies whether to verify the remote key using DNS and SSHFP
resource records. If this option is set to yes, the client will
implicitly trust keys that match a secure fingerprint from DNS.
Insecure fingerprints will be handled as if this option was set
to ask. If this option is set to ask, information on fingerprint
match will be displayed, but the user will still need to confirm
new host keys according to the StrictHostKeyChecking option. The
default is no.
See also VERIFYING HOST KEYS in ssh(1).
VisualHostKey
If this flag is set to yes, an ASCII art representation of the
remote host key fingerprint is printed in addition to the
fingerprint string at login and for unknown host keys. If this
flag is set to no (the default), no fingerprint strings are
printed at login and only the fingerprint string will be printed
for unknown host keys.
XAuthLocation
Specifies the full pathname of the xauth(1) program. The default
is /usr/X11R6/bin/xauth.
PATTERNS
A pattern consists of zero or more non-whitespace characters, M-bM-^@M-^X*M-bM-^@M-^Y (a
wildcard that matches zero or more characters), or M-bM-^@M-^X?M-bM-^@M-^Y (a wildcard that
matches exactly one character). For example, to specify a set of
declarations for any host in the ".co.uk" set of domains, the following
pattern could be used:
Host *.co.uk
The following pattern would match any host in the 192.168.0.[0-9] network
range:
Host 192.168.0.?
A pattern-list is a comma-separated list of patterns. Patterns within
pattern-lists may be negated by preceding them with an exclamation mark
(M-bM-^@M-^X!M-bM-^@M-^Y). For example, to allow a key to be used from anywhere within an
organization except from the "dialup" pool, the following entry (in
authorized_keys) could be used:
from="!*.dialup.example.com,*.example.com"
Note that a negated match will never produce a positive result by itself.
For example, attempting to match "host3" against the following pattern-
list will fail:
from="!host1,!host2"
The solution here is to include a term that will yield a positive match,
such as a wildcard:
from="!host1,!host2,*"
TOKENS
Arguments to some keywords can make use of tokens, which are expanded at
runtime:
%% A literal M-bM-^@M-^X%M-bM-^@M-^Y.
%C Hash of %l%h%p%r.
%d Local user's home directory.
%h The remote hostname.
%i The local user ID.
%L The local hostname.
%l The local hostname, including the domain name.
%n The original remote hostname, as given on the command line.
%p The remote port.
%r The remote username.
%T The local tun(4) or tap(4) network interface assigned if
tunnel forwarding was requested, or "NONE" otherwise.
%u The local username.
Match exec accepts the tokens %%, %h, %i, %L, %l, %n, %p, %r, and %u.
CertificateFile accepts the tokens %%, %d, %h, %i, %l, %r, and %u.
ControlPath accepts the tokens %%, %C, %h, %i, %L, %l, %n, %p, %r, and
%u.
HostName accepts the tokens %% and %h.
IdentityAgent and IdentityFile accept the tokens %%, %d, %h, %i, %l, %r,
and %u.
LocalCommand accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, %T,
and %u.
ProxyCommand accepts the tokens %%, %h, %p, and %r.
RemoteCommand accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, and
%u.
FILES
~/.ssh/config
This is the per-user configuration file. The format of this file
is described above. This file is used by the SSH client.
Because of the potential for abuse, this file must have strict
- permissions: read/write for the user, and not accessible by
- others.
+ permissions: read/write for the user, and not writable by others.
/etc/ssh/ssh_config
Systemwide configuration file. This file provides defaults for
those values that are not specified in the user's configuration
file, and for those users who do not have a configuration file.
This file must be world-readable.
SEE ALSO
ssh(1)
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
-OpenBSD 6.4 October 3, 2018 OpenBSD 6.4
+OpenBSD 6.5 March 1, 2019 OpenBSD 6.5
diff --git a/ssh_config.5 b/ssh_config.5
index 4d5b01d3eace..412629637fc5 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -1,1810 +1,1835 @@
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" As far as I am concerned, the code I have written for this software
.\" can be used freely for any purpose. Any derived versions of this
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.286 2018/10/03 06:38:35 djm Exp $
-.Dd $Mdocdate: October 3 2018 $
+.\" $OpenBSD: ssh_config.5,v 1.292 2019/03/01 02:16:47 djm Exp $
+.Dd $Mdocdate: March 1 2019 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
.Nm ssh_config
.Nd OpenSSH SSH client configuration files
.Sh DESCRIPTION
.Xr ssh 1
obtains configuration data from the following sources in
the following order:
.Pp
.Bl -enum -offset indent -compact
.It
command-line options
.It
user's configuration file
.Pq Pa ~/.ssh/config
.It
system-wide configuration file
.Pq Pa /etc/ssh/ssh_config
.El
.Pp
For each parameter, the first obtained value
will be used.
The configuration files contain sections separated by
.Cm Host
specifications, and that section is only applied for hosts that
match one of the patterns given in the specification.
The matched host name is usually the one given on the command line
(see the
.Cm CanonicalizeHostname
option for exceptions).
.Pp
Since the first obtained value for each parameter is used, more
host-specific declarations should be given near the beginning of the
file, and general defaults at the end.
.Pp
The file contains keyword-argument pairs, one per line.
Lines starting with
.Ql #
and empty lines are interpreted as comments.
Arguments may optionally be enclosed in double quotes
.Pq \&"
in order to represent arguments containing spaces.
Configuration options may be separated by whitespace or
optional whitespace and exactly one
.Ql = ;
the latter format is useful to avoid the need to quote whitespace
when specifying configuration options using the
.Nm ssh ,
.Nm scp ,
and
.Nm sftp
.Fl o
option.
.Pp
The possible
keywords and their meanings are as follows (note that
keywords are case-insensitive and arguments are case-sensitive):
.Bl -tag -width Ds
.It Cm Host
Restricts the following declarations (up to the next
.Cm Host
or
.Cm Match
keyword) to be only for those hosts that match one of the patterns
given after the keyword.
If more than one pattern is provided, they should be separated by whitespace.
A single
.Ql *
as a pattern can be used to provide global
defaults for all hosts.
The host is usually the
.Ar hostname
argument given on the command line
(see the
.Cm CanonicalizeHostname
keyword for exceptions).
.Pp
A pattern entry may be negated by prefixing it with an exclamation mark
.Pq Sq !\& .
If a negated entry is matched, then the
.Cm Host
entry is ignored, regardless of whether any other patterns on the line
match.
Negated matches are therefore useful to provide exceptions for wildcard
matches.
.Pp
See
.Sx PATTERNS
for more information on patterns.
.It Cm Match
Restricts the following declarations (up to the next
.Cm Host
or
.Cm Match
keyword) to be used only when the conditions following the
.Cm Match
keyword are satisfied.
Match conditions are specified using one or more criteria
or the single token
.Cm all
which always matches.
The available criteria keywords are:
.Cm canonical ,
+.Cm final ,
.Cm exec ,
.Cm host ,
.Cm originalhost ,
.Cm user ,
and
.Cm localuser .
The
.Cm all
criteria must appear alone or immediately after
-.Cm canonical .
+.Cm canonical
+or
+.Cm final .
Other criteria may be combined arbitrarily.
All criteria but
-.Cm all
+.Cm all ,
+.Cm canonical ,
and
-.Cm canonical
+.Cm final
require an argument.
Criteria may be negated by prepending an exclamation mark
.Pq Sq !\& .
.Pp
The
.Cm canonical
keyword matches only when the configuration file is being re-parsed
after hostname canonicalization (see the
.Cm CanonicalizeHostname
-option.)
+option).
This may be useful to specify conditions that work with canonical host
names only.
+.Pp
+The
+.Cm final
+keyword requests that the configuration be re-parsed (regardless of whether
+.Cm CanonicalizeHostname
+is enabled), and matches only during this final pass.
+If
+.Cm CanonicalizeHostname
+is enabled, then
+.Cm canonical
+and
+.Cm final
+match during the same pass.
+.Pp
The
.Cm exec
keyword executes the specified command under the user's shell.
If the command returns a zero exit status then the condition is considered true.
Commands containing whitespace characters must be quoted.
Arguments to
.Cm exec
accept the tokens described in the
.Sx TOKENS
section.
.Pp
The other keywords' criteria must be single entries or comma-separated
lists and may use the wildcard and negation operators described in the
.Sx PATTERNS
section.
The criteria for the
.Cm host
keyword are matched against the target hostname, after any substitution
by the
.Cm Hostname
or
.Cm CanonicalizeHostname
options.
The
.Cm originalhost
keyword matches against the hostname as it was specified on the command-line.
The
.Cm user
keyword matches against the target username on the remote host.
The
.Cm localuser
keyword matches against the name of the local user running
.Xr ssh 1
(this keyword may be useful in system-wide
.Nm
files).
.It Cm AddKeysToAgent
Specifies whether keys should be automatically added to a running
.Xr ssh-agent 1 .
If this option is set to
.Cm yes
and a key is loaded from a file, the key and its passphrase are added to
the agent with the default lifetime, as if by
.Xr ssh-add 1 .
If this option is set to
.Cm ask ,
.Xr ssh 1
will require confirmation using the
.Ev SSH_ASKPASS
program before adding a key (see
.Xr ssh-add 1
for details).
If this option is set to
.Cm confirm ,
each use of the key must be confirmed, as if the
.Fl c
option was specified to
.Xr ssh-add 1 .
If this option is set to
.Cm no ,
no keys are added to the agent.
The argument must be
.Cm yes ,
.Cm confirm ,
.Cm ask ,
or
.Cm no
(the default).
.It Cm AddressFamily
Specifies which address family to use when connecting.
Valid arguments are
.Cm any
(the default),
.Cm inet
(use IPv4 only), or
.Cm inet6
(use IPv6 only).
.It Cm BatchMode
If set to
.Cm yes ,
passphrase/password querying will be disabled.
This option is useful in scripts and other batch jobs where no user
is present to supply the password.
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm BindAddress
Use the specified address on the local machine as the source address of
the connection.
Only useful on systems with more than one address.
.It Cm BindInterface
Use the address of the specified interface on the local machine as the
source address of the connection.
.It Cm CanonicalDomains
When
.Cm CanonicalizeHostname
is enabled, this option specifies the list of domain suffixes in which to
search for the specified destination host.
.It Cm CanonicalizeFallbackLocal
Specifies whether to fail with an error when hostname canonicalization fails.
The default,
.Cm yes ,
will attempt to look up the unqualified hostname using the system resolver's
search rules.
A value of
.Cm no
will cause
.Xr ssh 1
to fail instantly if
.Cm CanonicalizeHostname
is enabled and the target hostname cannot be found in any of the domains
specified by
.Cm CanonicalDomains .
.It Cm CanonicalizeHostname
Controls whether explicit hostname canonicalization is performed.
The default,
.Cm no ,
is not to perform any name rewriting and let the system resolver handle all
hostname lookups.
If set to
.Cm yes
then, for connections that do not use a
.Cm ProxyCommand
or
.Cm ProxyJump ,
.Xr ssh 1
will attempt to canonicalize the hostname specified on the command line
using the
.Cm CanonicalDomains
suffixes and
.Cm CanonicalizePermittedCNAMEs
rules.
If
.Cm CanonicalizeHostname
is set to
.Cm always ,
then canonicalization is applied to proxied connections too.
.Pp
If this option is enabled, then the configuration files are processed
again using the new target name to pick up any new configuration in matching
.Cm Host
and
.Cm Match
stanzas.
.It Cm CanonicalizeMaxDots
Specifies the maximum number of dot characters in a hostname before
canonicalization is disabled.
The default, 1,
allows a single dot (i.e. hostname.subdomain).
.It Cm CanonicalizePermittedCNAMEs
Specifies rules to determine whether CNAMEs should be followed when
canonicalizing hostnames.
The rules consist of one or more arguments of
.Ar source_domain_list : Ns Ar target_domain_list ,
where
.Ar source_domain_list
is a pattern-list of domains that may follow CNAMEs in canonicalization,
and
.Ar target_domain_list
is a pattern-list of domains that they may resolve to.
.Pp
For example,
.Qq *.a.example.com:*.b.example.com,*.c.example.com
will allow hostnames matching
.Qq *.a.example.com
to be canonicalized to names in the
.Qq *.b.example.com
or
.Qq *.c.example.com
domains.
.It Cm CASignatureAlgorithms
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
The default is:
.Bd -literal -offset indent
ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
.Xr ssh 1
will not accept host certificates signed using algorithms other than those
specified.
.It Cm CertificateFile
Specifies a file from which the user's certificate is read.
A corresponding private key must be provided separately in order
to use this certificate either
from an
.Cm IdentityFile
directive or
.Fl i
flag to
.Xr ssh 1 ,
via
.Xr ssh-agent 1 ,
or via a
.Cm PKCS11Provider .
.Pp
Arguments to
.Cm CertificateFile
may use the tilde syntax to refer to a user's home directory
or the tokens described in the
.Sx TOKENS
section.
.Pp
It is possible to have multiple certificate files specified in
configuration files; these certificates will be tried in sequence.
Multiple
.Cm CertificateFile
directives will add to the list of certificates used for
authentication.
.It Cm ChallengeResponseAuthentication
Specifies whether to use challenge-response authentication.
The argument to this keyword must be
.Cm yes
(the default)
or
.Cm no .
.It Cm CheckHostIP
If set to
.Cm yes
(the default),
.Xr ssh 1
will additionally check the host IP address in the
.Pa known_hosts
file.
This allows it to detect if a host key changed due to DNS spoofing
and will add addresses of destination hosts to
.Pa ~/.ssh/known_hosts
in the process, regardless of the setting of
.Cm StrictHostKeyChecking .
If the option is set to
.Cm no ,
the check will not be executed.
.It Cm Ciphers
Specifies the ciphers allowed and their order of preference.
Multiple ciphers must be comma-separated.
If the specified value begins with a
.Sq +
character, then the specified ciphers will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The supported ciphers are:
.Bd -literal -offset indent
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
.Ed
.Pp
The default is:
.Bd -literal -offset indent
chacha20-poly1305@openssh.com,
aes128-ctr,aes192-ctr,aes256-ctr,
aes128-gcm@openssh.com,aes256-gcm@openssh.com
.Ed
.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClearAllForwardings
Specifies that all local, remote, and dynamic port forwardings
specified in the configuration files or on the command line be
cleared.
This option is primarily useful when used from the
.Xr ssh 1
command line to clear port forwardings set in
configuration files, and is automatically set by
.Xr scp 1
and
.Xr sftp 1 .
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm Compression
Specifies whether to use compression.
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm ConnectionAttempts
Specifies the number of tries (one per second) to make before exiting.
The argument must be an integer.
This may be useful in scripts if the connection sometimes fails.
The default is 1.
.It Cm ConnectTimeout
Specifies the timeout (in seconds) used when connecting to the
SSH server, instead of using the default system TCP timeout.
This value is used only when the target is down or really unreachable,
not when it refuses the connection.
.It Cm ControlMaster
Enables the sharing of multiple sessions over a single network connection.
When set to
.Cm yes ,
.Xr ssh 1
will listen for connections on a control socket specified using the
.Cm ControlPath
argument.
Additional sessions can connect to this socket using the same
.Cm ControlPath
with
.Cm ControlMaster
set to
.Cm no
(the default).
These sessions will try to reuse the master instance's network connection
rather than initiating new ones, but will fall back to connecting normally
if the control socket does not exist, or is not listening.
.Pp
Setting this to
.Cm ask
will cause
.Xr ssh 1
to listen for control connections, but require confirmation using
.Xr ssh-askpass 1 .
If the
.Cm ControlPath
cannot be opened,
.Xr ssh 1
will continue without connecting to a master instance.
.Pp
X11 and
.Xr ssh-agent 1
forwarding is supported over these multiplexed connections, however the
display and agent forwarded will be the one belonging to the master
connection i.e. it is not possible to forward multiple displays or agents.
.Pp
Two additional options allow for opportunistic multiplexing: try to use a
master connection but fall back to creating a new one if one does not already
exist.
These options are:
.Cm auto
and
.Cm autoask .
The latter requires confirmation like the
.Cm ask
option.
.It Cm ControlPath
Specify the path to the control socket used for connection sharing as described
in the
.Cm ControlMaster
section above or the string
.Cm none
to disable connection sharing.
Arguments to
.Cm ControlPath
may use the tilde syntax to refer to a user's home directory
or the tokens described in the
.Sx TOKENS
section.
It is recommended that any
.Cm ControlPath
used for opportunistic connection sharing include
at least %h, %p, and %r (or alternatively %C) and be placed in a directory
that is not writable by other users.
This ensures that shared connections are uniquely identified.
.It Cm ControlPersist
When used in conjunction with
.Cm ControlMaster ,
specifies that the master connection should remain open
in the background (waiting for future client connections)
after the initial client connection has been closed.
If set to
.Cm no ,
then the master connection will not be placed into the background,
and will close as soon as the initial client connection is closed.
If set to
.Cm yes
or 0,
then the master connection will remain in the background indefinitely
(until killed or closed via a mechanism such as the
.Qq ssh -O exit ) .
If set to a time in seconds, or a time in any of the formats documented in
.Xr sshd_config 5 ,
then the backgrounded master connection will automatically terminate
after it has remained idle (with no client connections) for the
specified time.
.It Cm DynamicForward
Specifies that a TCP port on the local machine be forwarded
over the secure channel, and the application
protocol is then used to determine where to connect to from the
remote machine.
.Pp
The argument must be
.Sm off
.Oo Ar bind_address : Oc Ar port .
.Sm on
IPv6 addresses can be specified by enclosing addresses in square brackets.
By default, the local port is bound in accordance with the
.Cm GatewayPorts
setting.
However, an explicit
.Ar bind_address
may be used to bind the connection to a specific address.
The
.Ar bind_address
of
.Cm localhost
indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
.Pp
Currently the SOCKS4 and SOCKS5 protocols are supported, and
.Xr ssh 1
will act as a SOCKS server.
Multiple forwardings may be specified, and
additional forwardings can be given on the command line.
Only the superuser can forward privileged ports.
.It Cm EnableSSHKeysign
Setting this option to
.Cm yes
in the global client configuration file
.Pa /etc/ssh/ssh_config
enables the use of the helper program
.Xr ssh-keysign 8
during
.Cm HostbasedAuthentication .
The argument must be
.Cm yes
or
.Cm no
(the default).
This option should be placed in the non-hostspecific section.
See
.Xr ssh-keysign 8
for more information.
.It Cm EscapeChar
Sets the escape character (default:
.Ql ~ ) .
The escape character can also
be set on the command line.
The argument should be a single character,
.Ql ^
followed by a letter, or
.Cm none
to disable the escape
character entirely (making the connection transparent for binary
data).
.It Cm ExitOnForwardFailure
Specifies whether
.Xr ssh 1
should terminate the connection if it cannot set up all requested
dynamic, tunnel, local, and remote port forwardings, (e.g.\&
if either end is unable to bind and listen on a specified port).
Note that
.Cm ExitOnForwardFailure
does not apply to connections made over port forwardings and will not,
for example, cause
.Xr ssh 1
to exit if TCP connections to the ultimate forwarding destination fail.
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm FingerprintHash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
.Cm md5
and
.Cm sha256
(the default).
.It Cm ForwardAgent
Specifies whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
The argument must be
.Cm yes
or
.Cm no
(the default).
.Pp
Agent forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host
(for the agent's Unix-domain socket)
can access the local agent through the forwarded connection.
An attacker cannot obtain key material from the agent,
however they can perform operations on the keys that enable them to
authenticate using the identities loaded into the agent.
.It Cm ForwardX11
Specifies whether X11 connections will be automatically redirected
over the secure channel and
.Ev DISPLAY
set.
The argument must be
.Cm yes
or
.Cm no
(the default).
.Pp
X11 forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host
(for the user's X11 authorization database)
can access the local X11 display through the forwarded connection.
An attacker may then be able to perform activities such as keystroke monitoring
if the
.Cm ForwardX11Trusted
option is also enabled.
.It Cm ForwardX11Timeout
Specify a timeout for untrusted X11 forwarding
using the format described in the
.Sx TIME FORMATS
section of
.Xr sshd_config 5 .
X11 connections received by
.Xr ssh 1
after this time will be refused.
Setting
.Cm ForwardX11Timeout
to zero will disable the timeout and permit X11 forwarding for the life
of the connection.
The default is to disable untrusted X11 forwarding after twenty minutes has
elapsed.
.It Cm ForwardX11Trusted
If this option is set to
.Cm yes ,
remote X11 clients will have full access to the original X11 display.
.Pp
If this option is set to
.Cm no
(the default),
remote X11 clients will be considered untrusted and prevented
from stealing or tampering with data belonging to trusted X11
clients.
Furthermore, the
.Xr xauth 1
token used for the session will be set to expire after 20 minutes.
Remote clients will be refused access after this time.
.Pp
See the X11 SECURITY extension specification for full details on
the restrictions imposed on untrusted clients.
.It Cm GatewayPorts
Specifies whether remote hosts are allowed to connect to local
forwarded ports.
By default,
.Xr ssh 1
binds local port forwardings to the loopback address.
This prevents other remote hosts from connecting to forwarded ports.
.Cm GatewayPorts
can be used to specify that ssh
should bind local port forwardings to the wildcard address,
thus allowing remote hosts to connect to forwarded ports.
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm GlobalKnownHostsFile
Specifies one or more files to use for the global
host key database, separated by whitespace.
The default is
.Pa /etc/ssh/ssh_known_hosts ,
.Pa /etc/ssh/ssh_known_hosts2 .
.It Cm GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is
.Cm no .
.It Cm GSSAPIDelegateCredentials
Forward (delegate) credentials to the server.
The default is
.Cm no .
.It Cm HashKnownHosts
Indicates that
.Xr ssh 1
should hash host names and addresses when they are added to
.Pa ~/.ssh/known_hosts .
These hashed names may be used normally by
.Xr ssh 1
and
.Xr sshd 8 ,
but they do not reveal identifying information should the file's contents
be disclosed.
The default is
.Cm no .
Note that existing names and addresses in known hosts files
will not be converted automatically,
but may be manually hashed using
.Xr ssh-keygen 1 .
.It Cm HostbasedAuthentication
Specifies whether to try rhosts based authentication with public key
authentication.
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm HostbasedKeyTypes
Specifies the key types that will be used for hostbased authentication
as a comma-separated list of patterns.
Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
The
.Fl Q
option of
.Xr ssh 1
may be used to list supported key types.
.It Cm HostKeyAlgorithms
Specifies the host key algorithms
that the client wants to use in order of preference.
Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
If hostkeys are known for the destination host then this default is modified
to prefer their algorithms.
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
.It Cm HostKeyAlias
Specifies an alias that should be used instead of the
real host name when looking up or saving the host key
in the host key database files and when validating host certificates.
This option is useful for tunneling SSH connections
or for multiple servers running on a single host.
.It Cm HostName
Specifies the real host name to log into.
This can be used to specify nicknames or abbreviations for hosts.
Arguments to
.Cm HostName
accept the tokens described in the
.Sx TOKENS
section.
Numeric IP addresses are also permitted (both on the command line and in
.Cm HostName
specifications).
The default is the name given on the command line.
.It Cm IdentitiesOnly
Specifies that
.Xr ssh 1
should only use the authentication identity and certificate files explicitly
configured in the
.Nm
files
or passed on the
.Xr ssh 1
command-line,
even if
.Xr ssh-agent 1
or a
.Cm PKCS11Provider
offers more identities.
The argument to this keyword must be
.Cm yes
or
.Cm no
(the default).
This option is intended for situations where ssh-agent
offers many different identities.
.It Cm IdentityAgent
Specifies the
.Ux Ns -domain
socket used to communicate with the authentication agent.
.Pp
This option overrides the
.Ev SSH_AUTH_SOCK
environment variable and can be used to select a specific agent.
Setting the socket name to
.Cm none
disables the use of an authentication agent.
If the string
.Qq SSH_AUTH_SOCK
is specified, the location of the socket will be read from the
.Ev SSH_AUTH_SOCK
environment variable.
Otherwise if the specified value begins with a
.Sq $
character, then it will be treated as an environment variable containing
the location of the socket.
.Pp
Arguments to
.Cm IdentityAgent
may use the tilde syntax to refer to a user's home directory
or the tokens described in the
.Sx TOKENS
section.
.It Cm IdentityFile
Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA authentication
identity is read.
The default is
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
.Pa ~/.ssh/id_ed25519
and
.Pa ~/.ssh/id_rsa .
Additionally, any identities represented by the authentication agent
will be used for authentication unless
.Cm IdentitiesOnly
is set.
If no certificates have been explicitly specified by
.Cm CertificateFile ,
.Xr ssh 1
will try to load certificate information from the filename obtained by
appending
.Pa -cert.pub
to the path of a specified
.Cm IdentityFile .
.Pp
Arguments to
.Cm IdentityFile
may use the tilde syntax to refer to a user's home directory
or the tokens described in the
.Sx TOKENS
section.
.Pp
It is possible to have
multiple identity files specified in configuration files; all these
identities will be tried in sequence.
Multiple
.Cm IdentityFile
directives will add to the list of identities tried (this behaviour
differs from that of other configuration directives).
.Pp
.Cm IdentityFile
may be used in conjunction with
.Cm IdentitiesOnly
to select which identities in an agent are offered during authentication.
.Cm IdentityFile
may also be used in conjunction with
.Cm CertificateFile
in order to provide any certificate also needed for authentication with
the identity.
.It Cm IgnoreUnknown
Specifies a pattern-list of unknown options to be ignored if they are
encountered in configuration parsing.
This may be used to suppress errors if
.Nm
contains options that are unrecognised by
.Xr ssh 1 .
It is recommended that
.Cm IgnoreUnknown
be listed early in the configuration file as it will not be applied
to unknown options that appear before it.
.It Cm Include
Include the specified configuration file(s).
Multiple pathnames may be specified and each pathname may contain
.Xr glob 7
wildcards and, for user configurations, shell-like
.Sq ~
references to user home directories.
Files without absolute paths are assumed to be in
.Pa ~/.ssh
if included in a user configuration file or
.Pa /etc/ssh
if included from the system configuration file.
.Cm Include
directive may appear inside a
.Cm Match
or
.Cm Host
block
to perform conditional inclusion.
.It Cm IPQoS
Specifies the IPv4 type-of-service or DSCP class for connections.
Accepted values are
.Cm af11 ,
.Cm af12 ,
.Cm af13 ,
.Cm af21 ,
.Cm af22 ,
.Cm af23 ,
.Cm af31 ,
.Cm af32 ,
.Cm af33 ,
.Cm af41 ,
.Cm af42 ,
.Cm af43 ,
.Cm cs0 ,
.Cm cs1 ,
.Cm cs2 ,
.Cm cs3 ,
.Cm cs4 ,
.Cm cs5 ,
.Cm cs6 ,
.Cm cs7 ,
.Cm ef ,
.Cm lowdelay ,
.Cm throughput ,
.Cm reliability ,
a numeric value, or
.Cm none
to use the operating system default.
This option may take one or two arguments, separated by whitespace.
If one argument is specified, it is used as the packet class unconditionally.
If two values are specified, the first is automatically selected for
interactive sessions and the second for non-interactive sessions.
The default is
.Cm af21
(Low-Latency Data)
for interactive sessions and
.Cm cs1
(Lower Effort)
for non-interactive sessions.
.It Cm KbdInteractiveAuthentication
Specifies whether to use keyboard-interactive authentication.
The argument to this keyword must be
.Cm yes
(the default)
or
.Cm no .
.It Cm KbdInteractiveDevices
Specifies the list of methods to use in keyboard-interactive authentication.
Multiple method names must be comma-separated.
The default is to use the server specified list.
The methods available vary depending on what the server supports.
For an OpenSSH server,
it may be zero or more of:
.Cm bsdauth
and
.Cm pam .
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
Alternately if the specified value begins with a
.Sq +
character, then the specified methods will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
from the default set instead of replacing them.
The default is:
.Bd -literal -offset indent
curve25519-sha256,curve25519-sha256@libssh.org,
ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
diffie-hellman-group-exchange-sha256,
diffie-hellman-group16-sha512,
diffie-hellman-group18-sha512,
-diffie-hellman-group-exchange-sha1,
diffie-hellman-group14-sha256,
diffie-hellman-group14-sha1
.Ed
.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
.It Cm LocalCommand
Specifies a command to execute on the local machine after successfully
connecting to the server.
The command string extends to the end of the line, and is executed with
the user's shell.
Arguments to
.Cm LocalCommand
accept the tokens described in the
.Sx TOKENS
section.
.Pp
The command is run synchronously and does not have access to the
session of the
.Xr ssh 1
that spawned it.
It should not be used for interactive commands.
.Pp
This directive is ignored unless
.Cm PermitLocalCommand
has been enabled.
.It Cm LocalForward
Specifies that a TCP port on the local machine be forwarded over
the secure channel to the specified host and port from the remote machine.
The first argument must be
.Sm off
.Oo Ar bind_address : Oc Ar port
.Sm on
and the second argument must be
.Ar host : Ns Ar hostport .
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional forwardings can be
given on the command line.
Only the superuser can forward privileged ports.
By default, the local port is bound in accordance with the
.Cm GatewayPorts
setting.
However, an explicit
.Ar bind_address
may be used to bind the connection to a specific address.
The
.Ar bind_address
of
.Cm localhost
indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
.It Cm LogLevel
Gives the verbosity level that is used when logging messages from
.Xr ssh 1 .
The possible values are:
QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
The default is INFO.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of verbose output.
.It Cm MACs
Specifies the MAC (message authentication code) algorithms
in order of preference.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified value begins with a
.Sq +
character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The algorithms that contain
.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
.Pp
The default is:
.Bd -literal -offset indent
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
hmac-sha1-etm@openssh.com,
umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-sha1
.Ed
.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm NoHostAuthenticationForLocalhost
Disable host authentication for localhost (loopback addresses).
The argument to this keyword must be
.Cm yes
or
.Cm no
(the default).
.It Cm NumberOfPasswordPrompts
Specifies the number of password prompts before giving up.
The argument to this keyword must be an integer.
The default is 3.
.It Cm PasswordAuthentication
Specifies whether to use password authentication.
The argument to this keyword must be
.Cm yes
(the default)
or
.Cm no .
.It Cm PermitLocalCommand
Allow local command execution via the
.Ic LocalCommand
option or using the
.Ic !\& Ns Ar command
escape sequence in
.Xr ssh 1 .
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm PKCS11Provider
-Specifies which PKCS#11 provider to use.
-The argument to this keyword is the PKCS#11 shared library
+Specifies which PKCS#11 provider to use or
+.Cm none
+to indicate that no provider should be used (the default).
+The argument to this keyword is a path to the PKCS#11 shared library
.Xr ssh 1
-should use to communicate with a PKCS#11 token providing the user's
-private RSA key.
+should use to communicate with a PKCS#11 token providing keys for user
+authentication.
.It Cm Port
Specifies the port number to connect on the remote host.
The default is 22.
.It Cm PreferredAuthentications
Specifies the order in which the client should try authentication methods.
This allows a client to prefer one method (e.g.\&
.Cm keyboard-interactive )
over another method (e.g.\&
.Cm password ) .
The default is:
.Bd -literal -offset indent
gssapi-with-mic,hostbased,publickey,
keyboard-interactive,password
.Ed
.It Cm ProxyCommand
Specifies the command to use to connect to the server.
The command
string extends to the end of the line, and is executed
using the user's shell
.Ql exec
directive to avoid a lingering shell process.
.Pp
Arguments to
.Cm ProxyCommand
accept the tokens described in the
.Sx TOKENS
section.
The command can be basically anything,
and should read from its standard input and write to its standard output.
It should eventually connect an
.Xr sshd 8
server running on some machine, or execute
.Ic sshd -i
somewhere.
Host key management will be done using the
HostName of the host being connected (defaulting to the name typed by
the user).
Setting the command to
.Cm none
disables this option entirely.
Note that
.Cm CheckHostIP
is not available for connects with a proxy command.
.Pp
This directive is useful in conjunction with
.Xr nc 1
and its proxy support.
For example, the following directive would connect via an HTTP proxy at
192.0.2.0:
.Bd -literal -offset 3n
ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p
.Ed
.It Cm ProxyJump
Specifies one or more jump proxies as either
.Xo
.Sm off
.Op Ar user No @
.Ar host
.Op : Ns Ar port
.Sm on
or an ssh URI
.Xc .
Multiple proxies may be separated by comma characters and will be visited
sequentially.
Setting this option will cause
.Xr ssh 1
to connect to the target host by first making a
.Xr ssh 1
connection to the specified
.Cm ProxyJump
host and then establishing a
TCP forwarding to the ultimate target from there.
.Pp
Note that this option will compete with the
.Cm ProxyCommand
option - whichever is specified first will prevent later instances of the
other from taking effect.
+.Pp
+Note also that the configuration for the destination host (either supplied
+via the command-line or the configuration file) is not generally applied
+to jump hosts.
+.Pa ~/.ssh/config
+should be used if specific configuration is required for jump hosts.
.It Cm ProxyUseFdpass
Specifies that
.Cm ProxyCommand
will pass a connected file descriptor back to
.Xr ssh 1
instead of continuing to execute and pass data.
The default is
.Cm no .
.It Cm PubkeyAcceptedKeyTypes
Specifies the key types that will be used for public key authentication
as a comma-separated list of patterns.
Alternately if the specified value begins with a
.Sq +
character, then the key types after it will be appended to the default
instead of replacing it.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
.It Cm PubkeyAuthentication
Specifies whether to try public key authentication.
The argument to this keyword must be
.Cm yes
(the default)
or
.Cm no .
.It Cm RekeyLimit
Specifies the maximum amount of data that may be transmitted before the
session key is renegotiated, optionally followed a maximum amount of
time that may pass before the session key is renegotiated.
The first argument is specified in bytes and may have a suffix of
.Sq K ,
.Sq M ,
or
.Sq G
to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
The default is between
.Sq 1G
and
.Sq 4G ,
depending on the cipher.
The optional second value is specified in seconds and may use any of the
units documented in the
.Sx TIME FORMATS
section of
.Xr sshd_config 5 .
The default value for
.Cm RekeyLimit
is
.Cm default none ,
which means that rekeying is performed after the cipher's default amount
of data has been sent or received and no time based rekeying is done.
.It Cm RemoteCommand
Specifies a command to execute on the remote machine after successfully
connecting to the server.
The command string extends to the end of the line, and is executed with
the user's shell.
Arguments to
.Cm RemoteCommand
accept the tokens described in the
.Sx TOKENS
section.
.It Cm RemoteForward
Specifies that a TCP port on the remote machine be forwarded over
the secure channel.
The remote port may either be forwarded to a specified host and port
from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote
client to connect to arbitrary destinations from the local machine.
The first argument must be
.Sm off
.Oo Ar bind_address : Oc Ar port
.Sm on
If forwarding to a specific destination then the second argument must be
.Ar host : Ns Ar hostport ,
otherwise if no destination argument is specified then the remote forwarding
will be established as a SOCKS proxy.
.Pp
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional
forwardings can be given on the command line.
Privileged ports can be forwarded only when
logging in as root on the remote machine.
.Pp
If the
.Ar port
argument is 0,
the listen port will be dynamically allocated on the server and reported
to the client at run time.
.Pp
If the
.Ar bind_address
is not specified, the default is to only bind to loopback addresses.
If the
.Ar bind_address
is
.Ql *
or an empty string, then the forwarding is requested to listen on all
interfaces.
Specifying a remote
.Ar bind_address
will only succeed if the server's
.Cm GatewayPorts
option is enabled (see
.Xr sshd_config 5 ) .
.It Cm RequestTTY
Specifies whether to request a pseudo-tty for the session.
The argument may be one of:
.Cm no
(never request a TTY),
.Cm yes
(always request a TTY when standard input is a TTY),
.Cm force
(always request a TTY) or
.Cm auto
(request a TTY when opening a login session).
This option mirrors the
.Fl t
and
.Fl T
flags for
.Xr ssh 1 .
.It Cm RevokedHostKeys
Specifies revoked host public keys.
Keys listed in this file will be refused for host authentication.
Note that if this file does not exist or is not readable,
then host authentication will be refused for all hosts.
Keys may be specified as a text file, listing one public key per line, or as
an OpenSSH Key Revocation List (KRL) as generated by
.Xr ssh-keygen 1 .
For more information on KRLs, see the KEY REVOCATION LISTS section in
.Xr ssh-keygen 1 .
.It Cm SendEnv
Specifies what variables from the local
.Xr environ 7
should be sent to the server.
The server must also support it, and the server must be configured to
accept these environment variables.
Note that the
.Ev TERM
environment variable is always sent whenever a
pseudo-terminal is requested as it is required by the protocol.
Refer to
.Cm AcceptEnv
in
.Xr sshd_config 5
for how to configure the server.
Variables are specified by name, which may contain wildcard characters.
Multiple environment variables may be separated by whitespace or spread
across multiple
.Cm SendEnv
directives.
.Pp
See
.Sx PATTERNS
for more information on patterns.
.Pp
It is possible to clear previously set
.Cm SendEnv
variable names by prefixing patterns with
.Pa - .
The default is not to send any environment variables.
.It Cm ServerAliveCountMax
Sets the number of server alive messages (see below) which may be
sent without
.Xr ssh 1
receiving any messages back from the server.
If this threshold is reached while server alive messages are being sent,
ssh will disconnect from the server, terminating the session.
It is important to note that the use of server alive messages is very
different from
.Cm TCPKeepAlive
(below).
The server alive messages are sent through the encrypted channel
and therefore will not be spoofable.
The TCP keepalive option enabled by
.Cm TCPKeepAlive
is spoofable.
The server alive mechanism is valuable when the client or
server depend on knowing when a connection has become inactive.
.Pp
The default value is 3.
If, for example,
.Cm ServerAliveInterval
(see below) is set to 15 and
.Cm ServerAliveCountMax
is left at the default, if the server becomes unresponsive,
ssh will disconnect after approximately 45 seconds.
.It Cm ServerAliveInterval
Sets a timeout interval in seconds after which if no data has been received
from the server,
.Xr ssh 1
will send a message through the encrypted
channel to request a response from the server.
The default
is 0, indicating that these messages will not be sent to the server.
.It Cm SetEnv
Directly specify one or more environment variables and their contents to
be sent to the server.
Similarly to
.Cm SendEnv ,
the server must be prepared to accept the environment variable.
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
used when creating a Unix-domain socket file for local or remote
port forwarding.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The default value is 0177, which creates a Unix-domain socket file that is
readable and writable only by the owner.
Note that not all operating systems honor the file mode on Unix-domain
socket files.
.It Cm StreamLocalBindUnlink
Specifies whether to remove an existing Unix-domain socket file for local
or remote port forwarding before creating a new one.
If the socket file already exists and
.Cm StreamLocalBindUnlink
is not enabled,
.Nm ssh
will be unable to forward the port to the Unix-domain socket file.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The argument must be
.Cm yes
or
.Cm no
(the default).
.It Cm StrictHostKeyChecking
If this flag is set to
.Cm yes ,
.Xr ssh 1
will never automatically add host keys to the
.Pa ~/.ssh/known_hosts
file, and refuses to connect to hosts whose host key has changed.
This provides maximum protection against man-in-the-middle (MITM) attacks,
though it can be annoying when the
.Pa /etc/ssh/ssh_known_hosts
file is poorly maintained or when connections to new hosts are
frequently made.
This option forces the user to manually
add all new hosts.
.Pp
If this flag is set to
.Dq accept-new
then ssh will automatically add new host keys to the user
known hosts files, but will not permit connections to hosts with
changed host keys.
If this flag is set to
.Dq no
or
.Dq off ,
ssh will automatically add new host keys to the user known hosts files
and allow connections to hosts with changed hostkeys to proceed,
subject to some restrictions.
If this flag is set to
.Cm ask
(the default),
new host keys
will be added to the user known host files only after the user
has confirmed that is what they really want to do, and
ssh will refuse to connect to hosts whose host key has changed.
The host keys of
known hosts will be verified automatically in all cases.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr ssh 1 .
The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is USER.
.It Cm TCPKeepAlive
Specifies whether the system should send TCP keepalive messages to the
other side.
If they are sent, death of the connection or crash of one
of the machines will be properly noticed.
However, this means that
connections will die if the route is down temporarily, and some people
find it annoying.
.Pp
The default is
.Cm yes
(to send TCP keepalive messages), and the client will notice
if the network goes down or the remote host dies.
This is important in scripts, and many users want it too.
.Pp
To disable TCP keepalive messages, the value should be set to
.Cm no .
See also
.Cm ServerAliveInterval
for protocol-level keepalives.
.It Cm Tunnel
Request
.Xr tun 4
device forwarding between the client and the server.
The argument must be
.Cm yes ,
.Cm point-to-point
(layer 3),
.Cm ethernet
(layer 2),
or
.Cm no
(the default).
Specifying
.Cm yes
requests the default tunnel mode, which is
.Cm point-to-point .
.It Cm TunnelDevice
Specifies the
.Xr tun 4
devices to open on the client
.Pq Ar local_tun
and the server
.Pq Ar remote_tun .
.Pp
The argument must be
.Sm off
.Ar local_tun Op : Ar remote_tun .
.Sm on
The devices may be specified by numerical ID or the keyword
.Cm any ,
which uses the next available tunnel device.
If
.Ar remote_tun
is not specified, it defaults to
.Cm any .
The default is
.Cm any:any .
.It Cm UpdateHostKeys
Specifies whether
.Xr ssh 1
should accept notifications of additional hostkeys from the server sent
after authentication has completed and add them to
.Cm UserKnownHostsFile .
The argument must be
.Cm yes ,
.Cm no
(the default) or
.Cm ask .
Enabling this option allows learning alternate hostkeys for a server
and supports graceful key rotation by allowing a server to send replacement
public keys before old ones are removed.
Additional hostkeys are only accepted if the key used to authenticate the
host was already trusted or explicitly accepted by the user.
If
.Cm UpdateHostKeys
is set to
.Cm ask ,
then the user is asked to confirm the modifications to the known_hosts file.
Confirmation is currently incompatible with
.Cm ControlPersist ,
and will be disabled if it is enabled.
.Pp
Presently, only
.Xr sshd 8
from OpenSSH 6.8 and greater support the
.Qq hostkeys@openssh.com
protocol extension used to inform the client of all the server's hostkeys.
.It Cm User
Specifies the user to log in as.
This can be useful when a different user name is used on different machines.
This saves the trouble of
having to remember to give the user name on the command line.
.It Cm UserKnownHostsFile
Specifies one or more files to use for the user
host key database, separated by whitespace.
The default is
.Pa ~/.ssh/known_hosts ,
.Pa ~/.ssh/known_hosts2 .
.It Cm VerifyHostKeyDNS
Specifies whether to verify the remote key using DNS and SSHFP resource
records.
If this option is set to
.Cm yes ,
the client will implicitly trust keys that match a secure fingerprint
from DNS.
Insecure fingerprints will be handled as if this option was set to
.Cm ask .
If this option is set to
.Cm ask ,
information on fingerprint match will be displayed, but the user will still
need to confirm new host keys according to the
.Cm StrictHostKeyChecking
option.
The default is
.Cm no .
.Pp
See also
.Sx VERIFYING HOST KEYS
in
.Xr ssh 1 .
.It Cm VisualHostKey
If this flag is set to
.Cm yes ,
an ASCII art representation of the remote host key fingerprint is
printed in addition to the fingerprint string at login and
for unknown host keys.
If this flag is set to
.Cm no
(the default),
no fingerprint strings are printed at login and
only the fingerprint string will be printed for unknown host keys.
.It Cm XAuthLocation
Specifies the full pathname of the
.Xr xauth 1
program.
The default is
.Pa /usr/X11R6/bin/xauth .
.El
.Sh PATTERNS
A
.Em pattern
consists of zero or more non-whitespace characters,
.Sq *
(a wildcard that matches zero or more characters),
or
.Sq ?\&
(a wildcard that matches exactly one character).
For example, to specify a set of declarations for any host in the
.Qq .co.uk
set of domains,
the following pattern could be used:
.Pp
.Dl Host *.co.uk
.Pp
The following pattern
would match any host in the 192.168.0.[0-9] network range:
.Pp
.Dl Host 192.168.0.?
.Pp
A
.Em pattern-list
is a comma-separated list of patterns.
Patterns within pattern-lists may be negated
by preceding them with an exclamation mark
.Pq Sq !\& .
For example,
to allow a key to be used from anywhere within an organization
except from the
.Qq dialup
pool,
the following entry (in authorized_keys) could be used:
.Pp
.Dl from=\&"!*.dialup.example.com,*.example.com\&"
.Pp
Note that a negated match will never produce a positive result by itself.
For example, attempting to match
.Qq host3
against the following pattern-list will fail:
.Pp
.Dl from=\&"!host1,!host2\&"
.Pp
The solution here is to include a term that will yield a positive match,
such as a wildcard:
.Pp
.Dl from=\&"!host1,!host2,*\&"
.Sh TOKENS
Arguments to some keywords can make use of tokens,
which are expanded at runtime:
.Pp
.Bl -tag -width XXXX -offset indent -compact
.It %%
A literal
.Sq % .
.It \&%C
Hash of %l%h%p%r.
.It %d
Local user's home directory.
.It %h
The remote hostname.
.It %i
The local user ID.
.It %L
The local hostname.
.It %l
The local hostname, including the domain name.
.It %n
The original remote hostname, as given on the command line.
.It %p
The remote port.
.It %r
The remote username.
.It \&%T
The local
.Xr tun 4
or
.Xr tap 4
network interface assigned if
tunnel forwarding was requested, or
.Qq NONE
otherwise.
.It %u
The local username.
.El
.Pp
.Cm Match exec
accepts the tokens %%, %h, %i, %L, %l, %n, %p, %r, and %u.
.Pp
.Cm CertificateFile
accepts the tokens %%, %d, %h, %i, %l, %r, and %u.
.Pp
.Cm ControlPath
accepts the tokens %%, %C, %h, %i, %L, %l, %n, %p, %r, and %u.
.Pp
.Cm HostName
accepts the tokens %% and %h.
.Pp
.Cm IdentityAgent
and
.Cm IdentityFile
accept the tokens %%, %d, %h, %i, %l, %r, and %u.
.Pp
.Cm LocalCommand
accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, %T, and %u.
.Pp
.Cm ProxyCommand
accepts the tokens %%, %h, %p, and %r.
.Pp
.Cm RemoteCommand
accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, and %u.
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/config
This is the per-user configuration file.
The format of this file is described above.
This file is used by the SSH client.
Because of the potential for abuse, this file must have strict permissions:
-read/write for the user, and not accessible by others.
+read/write for the user, and not writable by others.
.It Pa /etc/ssh/ssh_config
Systemwide configuration file.
This file provides defaults for those
values that are not specified in the user's configuration file, and
for those users who do not have a configuration file.
This file must be world-readable.
.El
.Sh SEE ALSO
.Xr ssh 1
.Sh AUTHORS
.An -nosplit
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by
.An Tatu Ylonen .
.An Aaron Campbell , Bob Beck , Markus Friedl ,
.An Niels Provos , Theo de Raadt
and
.An Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
.An Markus Friedl
contributed the support for SSH protocol versions 1.5 and 2.0.
diff --git a/sshbuf-getput-crypto.c b/sshbuf-getput-crypto.c
index d0d791b50a34..3dd1e1446f17 100644
--- a/sshbuf-getput-crypto.c
+++ b/sshbuf-getput-crypto.c
@@ -1,224 +1,185 @@
-/* $OpenBSD: sshbuf-getput-crypto.c,v 1.5 2016/01/12 23:42:54 djm Exp $ */
+/* $OpenBSD: sshbuf-getput-crypto.c,v 1.7 2019/01/21 09:54:11 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define SSHBUF_INTERNAL
#include "includes.h"
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/bn.h>
#ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
#endif /* OPENSSL_HAS_ECC */
#include "ssherr.h"
#include "sshbuf.h"
int
-sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v)
+sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp)
{
+ BIGNUM *v;
const u_char *d;
size_t len;
int r;
+ if (valp != NULL)
+ *valp = NULL;
if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
return r;
- if (v != NULL && BN_bin2bn(d, len, v) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- return 0;
-}
-
-int
-sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v)
-{
- const u_char *d = sshbuf_ptr(buf);
- u_int16_t len_bits;
- size_t len_bytes;
-
- /* Length in bits */
- if (sshbuf_len(buf) < 2)
- return SSH_ERR_MESSAGE_INCOMPLETE;
- len_bits = PEEK_U16(d);
- len_bytes = (len_bits + 7) >> 3;
- if (len_bytes > SSHBUF_MAX_BIGNUM)
- return SSH_ERR_BIGNUM_TOO_LARGE;
- if (sshbuf_len(buf) < 2 + len_bytes)
- return SSH_ERR_MESSAGE_INCOMPLETE;
- if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if (sshbuf_consume(buf, 2 + len_bytes) != 0) {
- SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
- SSHBUF_ABORT();
- return SSH_ERR_INTERNAL_ERROR;
+ if (valp != NULL) {
+ if ((v = BN_new()) == NULL ||
+ BN_bin2bn(d, len, v) == NULL) {
+ BN_clear_free(v);
+ return SSH_ERR_ALLOC_FAIL;
+ }
+ *valp = v;
}
return 0;
}
#ifdef OPENSSL_HAS_ECC
static int
get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
{
/* Refuse overlong bignums */
if (len == 0 || len > SSHBUF_MAX_ECPOINT)
return SSH_ERR_ECPOINT_TOO_LARGE;
/* Only handle uncompressed points */
if (*d != POINT_CONVERSION_UNCOMPRESSED)
return SSH_ERR_INVALID_FORMAT;
if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
return 0;
}
int
sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
{
const u_char *d;
size_t len;
int r;
if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
return r;
if ((r = get_ec(d, len, v, g)) != 0)
return r;
/* Skip string */
if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
/* Shouldn't happen */
SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
SSHBUF_ABORT();
return SSH_ERR_INTERNAL_ERROR;
}
return 0;
}
int
sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
{
EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
int r;
const u_char *d;
size_t len;
if (pt == NULL) {
SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
return SSH_ERR_ALLOC_FAIL;
}
if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
EC_POINT_free(pt);
return r;
}
if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
EC_POINT_free(pt);
return r;
}
if (EC_KEY_set_public_key(v, pt) != 1) {
EC_POINT_free(pt);
return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
}
EC_POINT_free(pt);
/* Skip string */
if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
/* Shouldn't happen */
SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
SSHBUF_ABORT();
return SSH_ERR_INTERNAL_ERROR;
}
return 0;
}
#endif /* OPENSSL_HAS_ECC */
int
sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
{
u_char d[SSHBUF_MAX_BIGNUM + 1];
int len = BN_num_bytes(v), prepend = 0, r;
if (len < 0 || len > SSHBUF_MAX_BIGNUM)
return SSH_ERR_INVALID_ARGUMENT;
*d = '\0';
if (BN_bn2bin(v, d + 1) != len)
return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
/* If MSB is set, prepend a \0 */
if (len > 0 && (d[1] & 0x80) != 0)
prepend = 1;
if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
explicit_bzero(d, sizeof(d));
return r;
}
explicit_bzero(d, sizeof(d));
return 0;
}
-int
-sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v)
-{
- int r, len_bits = BN_num_bits(v);
- size_t len_bytes = (len_bits + 7) / 8;
- u_char d[SSHBUF_MAX_BIGNUM], *dp;
-
- if (len_bits < 0 || len_bytes > SSHBUF_MAX_BIGNUM)
- return SSH_ERR_INVALID_ARGUMENT;
- if (BN_bn2bin(v, d) != (int)len_bytes)
- return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
- if ((r = sshbuf_reserve(buf, len_bytes + 2, &dp)) < 0) {
- explicit_bzero(d, sizeof(d));
- return r;
- }
- POKE_U16(dp, len_bits);
- if (len_bytes != 0)
- memcpy(dp + 2, d, len_bytes);
- explicit_bzero(d, sizeof(d));
- return 0;
-}
-
#ifdef OPENSSL_HAS_ECC
int
sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
{
u_char d[SSHBUF_MAX_ECPOINT];
BN_CTX *bn_ctx;
size_t len;
int ret;
if ((bn_ctx = BN_CTX_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) {
BN_CTX_free(bn_ctx);
return SSH_ERR_INVALID_ARGUMENT;
}
if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
d, len, bn_ctx) != len) {
BN_CTX_free(bn_ctx);
return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
}
BN_CTX_free(bn_ctx);
ret = sshbuf_put_string(buf, d, len);
explicit_bzero(d, len);
return ret;
}
int
sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
{
return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
EC_KEY_get0_group(v));
}
#endif /* OPENSSL_HAS_ECC */
diff --git a/sshbuf.c b/sshbuf.c
index 20ddf9eb6272..adfddf7758c1 100644
--- a/sshbuf.c
+++ b/sshbuf.c
@@ -1,399 +1,402 @@
-/* $OpenBSD: sshbuf.c,v 1.12 2018/07/09 21:56:06 markus Exp $ */
+/* $OpenBSD: sshbuf.c,v 1.13 2018/11/16 06:10:29 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define SSHBUF_INTERNAL
#include "includes.h"
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ssherr.h"
#include "sshbuf.h"
#include "misc.h"
static inline int
sshbuf_check_sanity(const struct sshbuf *buf)
{
SSHBUF_TELL("sanity");
if (__predict_false(buf == NULL ||
(!buf->readonly && buf->d != buf->cd) ||
buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX ||
buf->cd == NULL ||
buf->max_size > SSHBUF_SIZE_MAX ||
buf->alloc > buf->max_size ||
buf->size > buf->alloc ||
buf->off > buf->size)) {
/* Do not try to recover from corrupted buffer internals */
SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
signal(SIGSEGV, SIG_DFL);
raise(SIGSEGV);
return SSH_ERR_INTERNAL_ERROR;
}
return 0;
}
static void
sshbuf_maybe_pack(struct sshbuf *buf, int force)
{
SSHBUF_DBG(("force %d", force));
SSHBUF_TELL("pre-pack");
if (buf->off == 0 || buf->readonly || buf->refcount > 1)
return;
if (force ||
(buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) {
memmove(buf->d, buf->d + buf->off, buf->size - buf->off);
buf->size -= buf->off;
buf->off = 0;
SSHBUF_TELL("packed");
}
}
struct sshbuf *
sshbuf_new(void)
{
struct sshbuf *ret;
if ((ret = calloc(sizeof(*ret), 1)) == NULL)
return NULL;
ret->alloc = SSHBUF_SIZE_INIT;
ret->max_size = SSHBUF_SIZE_MAX;
ret->readonly = 0;
ret->refcount = 1;
ret->parent = NULL;
if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) {
free(ret);
return NULL;
}
return ret;
}
struct sshbuf *
sshbuf_from(const void *blob, size_t len)
{
struct sshbuf *ret;
if (blob == NULL || len > SSHBUF_SIZE_MAX ||
(ret = calloc(sizeof(*ret), 1)) == NULL)
return NULL;
ret->alloc = ret->size = ret->max_size = len;
ret->readonly = 1;
ret->refcount = 1;
ret->parent = NULL;
ret->cd = blob;
ret->d = NULL;
return ret;
}
int
sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent)
{
int r;
if ((r = sshbuf_check_sanity(child)) != 0 ||
(r = sshbuf_check_sanity(parent)) != 0)
return r;
child->parent = parent;
child->parent->refcount++;
return 0;
}
struct sshbuf *
sshbuf_fromb(struct sshbuf *buf)
{
struct sshbuf *ret;
if (sshbuf_check_sanity(buf) != 0)
return NULL;
if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL)
return NULL;
if (sshbuf_set_parent(ret, buf) != 0) {
sshbuf_free(ret);
return NULL;
}
return ret;
}
void
sshbuf_free(struct sshbuf *buf)
{
if (buf == NULL)
return;
/*
* The following will leak on insane buffers, but this is the safest
* course of action - an invalid pointer or already-freed pointer may
* have been passed to us and continuing to scribble over memory would
* be bad.
*/
if (sshbuf_check_sanity(buf) != 0)
return;
- /*
- * If we are a child, the free our parent to decrement its reference
- * count and possibly free it.
- */
- sshbuf_free(buf->parent);
- buf->parent = NULL;
+
/*
* If we are a parent with still-extant children, then don't free just
* yet. The last child's call to sshbuf_free should decrement our
* refcount to 0 and trigger the actual free.
*/
buf->refcount--;
if (buf->refcount > 0)
return;
+
+ /*
+ * If we are a child, the free our parent to decrement its reference
+ * count and possibly free it.
+ */
+ sshbuf_free(buf->parent);
+ buf->parent = NULL;
+
if (!buf->readonly) {
explicit_bzero(buf->d, buf->alloc);
free(buf->d);
}
explicit_bzero(buf, sizeof(*buf));
free(buf);
}
void
sshbuf_reset(struct sshbuf *buf)
{
u_char *d;
if (buf->readonly || buf->refcount > 1) {
/* Nonsensical. Just make buffer appear empty */
buf->off = buf->size;
return;
}
(void) sshbuf_check_sanity(buf);
buf->off = buf->size = 0;
if (buf->alloc != SSHBUF_SIZE_INIT) {
if ((d = recallocarray(buf->d, buf->alloc, SSHBUF_SIZE_INIT,
1)) != NULL) {
buf->cd = buf->d = d;
buf->alloc = SSHBUF_SIZE_INIT;
}
}
explicit_bzero(buf->d, SSHBUF_SIZE_INIT);
}
size_t
sshbuf_max_size(const struct sshbuf *buf)
{
return buf->max_size;
}
size_t
sshbuf_alloc(const struct sshbuf *buf)
{
return buf->alloc;
}
const struct sshbuf *
sshbuf_parent(const struct sshbuf *buf)
{
return buf->parent;
}
u_int
sshbuf_refcount(const struct sshbuf *buf)
{
return buf->refcount;
}
int
sshbuf_set_max_size(struct sshbuf *buf, size_t max_size)
{
size_t rlen;
u_char *dp;
int r;
SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size));
if ((r = sshbuf_check_sanity(buf)) != 0)
return r;
if (max_size == buf->max_size)
return 0;
if (buf->readonly || buf->refcount > 1)
return SSH_ERR_BUFFER_READ_ONLY;
if (max_size > SSHBUF_SIZE_MAX)
return SSH_ERR_NO_BUFFER_SPACE;
/* pack and realloc if necessary */
sshbuf_maybe_pack(buf, max_size < buf->size);
if (max_size < buf->alloc && max_size > buf->size) {
if (buf->size < SSHBUF_SIZE_INIT)
rlen = SSHBUF_SIZE_INIT;
else
rlen = ROUNDUP(buf->size, SSHBUF_SIZE_INC);
if (rlen > max_size)
rlen = max_size;
SSHBUF_DBG(("new alloc = %zu", rlen));
if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL)
return SSH_ERR_ALLOC_FAIL;
buf->cd = buf->d = dp;
buf->alloc = rlen;
}
SSHBUF_TELL("new-max");
if (max_size < buf->alloc)
return SSH_ERR_NO_BUFFER_SPACE;
buf->max_size = max_size;
return 0;
}
size_t
sshbuf_len(const struct sshbuf *buf)
{
if (sshbuf_check_sanity(buf) != 0)
return 0;
return buf->size - buf->off;
}
size_t
sshbuf_avail(const struct sshbuf *buf)
{
if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1)
return 0;
return buf->max_size - (buf->size - buf->off);
}
const u_char *
sshbuf_ptr(const struct sshbuf *buf)
{
if (sshbuf_check_sanity(buf) != 0)
return NULL;
return buf->cd + buf->off;
}
u_char *
sshbuf_mutable_ptr(const struct sshbuf *buf)
{
if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1)
return NULL;
return buf->d + buf->off;
}
int
sshbuf_check_reserve(const struct sshbuf *buf, size_t len)
{
int r;
if ((r = sshbuf_check_sanity(buf)) != 0)
return r;
if (buf->readonly || buf->refcount > 1)
return SSH_ERR_BUFFER_READ_ONLY;
SSHBUF_TELL("check");
/* Check that len is reasonable and that max_size + available < len */
if (len > buf->max_size || buf->max_size - len < buf->size - buf->off)
return SSH_ERR_NO_BUFFER_SPACE;
return 0;
}
int
sshbuf_allocate(struct sshbuf *buf, size_t len)
{
size_t rlen, need;
u_char *dp;
int r;
SSHBUF_DBG(("allocate buf = %p len = %zu", buf, len));
if ((r = sshbuf_check_reserve(buf, len)) != 0)
return r;
/*
* If the requested allocation appended would push us past max_size
* then pack the buffer, zeroing buf->off.
*/
sshbuf_maybe_pack(buf, buf->size + len > buf->max_size);
SSHBUF_TELL("allocate");
if (len + buf->size <= buf->alloc)
return 0; /* already have it. */
/*
* Prefer to alloc in SSHBUF_SIZE_INC units, but
* allocate less if doing so would overflow max_size.
*/
need = len + buf->size - buf->alloc;
rlen = ROUNDUP(buf->alloc + need, SSHBUF_SIZE_INC);
SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
if (rlen > buf->max_size)
rlen = buf->alloc + need;
SSHBUF_DBG(("adjusted rlen %zu", rlen));
if ((dp = recallocarray(buf->d, buf->alloc, rlen, 1)) == NULL) {
SSHBUF_DBG(("realloc fail"));
return SSH_ERR_ALLOC_FAIL;
}
buf->alloc = rlen;
buf->cd = buf->d = dp;
if ((r = sshbuf_check_reserve(buf, len)) < 0) {
/* shouldn't fail */
return r;
}
SSHBUF_TELL("done");
return 0;
}
int
sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
{
u_char *dp;
int r;
if (dpp != NULL)
*dpp = NULL;
SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len));
if ((r = sshbuf_allocate(buf, len)) != 0)
return r;
dp = buf->d + buf->size;
buf->size += len;
if (dpp != NULL)
*dpp = dp;
return 0;
}
int
sshbuf_consume(struct sshbuf *buf, size_t len)
{
int r;
SSHBUF_DBG(("len = %zu", len));
if ((r = sshbuf_check_sanity(buf)) != 0)
return r;
if (len == 0)
return 0;
if (len > sshbuf_len(buf))
return SSH_ERR_MESSAGE_INCOMPLETE;
buf->off += len;
/* deal with empty buffer */
if (buf->off == buf->size)
buf->off = buf->size = 0;
SSHBUF_TELL("done");
return 0;
}
int
sshbuf_consume_end(struct sshbuf *buf, size_t len)
{
int r;
SSHBUF_DBG(("len = %zu", len));
if ((r = sshbuf_check_sanity(buf)) != 0)
return r;
if (len == 0)
return 0;
if (len > sshbuf_len(buf))
return SSH_ERR_MESSAGE_INCOMPLETE;
buf->size -= len;
SSHBUF_TELL("done");
return 0;
}
diff --git a/sshbuf.h b/sshbuf.h
index a43598cac4de..7900b82bac25 100644
--- a/sshbuf.h
+++ b/sshbuf.h
@@ -1,348 +1,346 @@
-/* $OpenBSD: sshbuf.h,v 1.11 2018/07/09 21:56:06 markus Exp $ */
+/* $OpenBSD: sshbuf.h,v 1.13 2019/01/21 09:54:11 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SSHBUF_H
#define _SSHBUF_H
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
#ifdef WITH_OPENSSL
# include <openssl/bn.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
#define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */
#define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */
#define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */
#define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */
/*
* NB. do not depend on the internals of this. It will be made opaque
* one day.
*/
struct sshbuf {
u_char *d; /* Data */
const u_char *cd; /* Const data */
size_t off; /* First available byte is buf->d + buf->off */
size_t size; /* Last byte is buf->d + buf->size - 1 */
size_t max_size; /* Maximum size of buffer */
size_t alloc; /* Total bytes allocated to buf->d */
int readonly; /* Refers to external, const data */
int dont_free; /* Kludge to support sshbuf_init */
u_int refcount; /* Tracks self and number of child buffers */
struct sshbuf *parent; /* If child, pointer to parent */
};
/*
* Create a new sshbuf buffer.
* Returns pointer to buffer on success, or NULL on allocation failure.
*/
struct sshbuf *sshbuf_new(void);
/*
* Create a new, read-only sshbuf buffer from existing data.
* Returns pointer to buffer on success, or NULL on allocation failure.
*/
struct sshbuf *sshbuf_from(const void *blob, size_t len);
/*
* Create a new, read-only sshbuf buffer from the contents of an existing
* buffer. The contents of "buf" must not change in the lifetime of the
* resultant buffer.
* Returns pointer to buffer on success, or NULL on allocation failure.
*/
struct sshbuf *sshbuf_fromb(struct sshbuf *buf);
/*
* Create a new, read-only sshbuf buffer from the contents of a string in
* an existing buffer (the string is consumed in the process).
* The contents of "buf" must not change in the lifetime of the resultant
* buffer.
* Returns pointer to buffer on success, or NULL on allocation failure.
*/
int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp);
/*
* Clear and free buf
*/
void sshbuf_free(struct sshbuf *buf);
/*
* Reset buf, clearing its contents. NB. max_size is preserved.
*/
void sshbuf_reset(struct sshbuf *buf);
/*
* Return the maximum size of buf
*/
size_t sshbuf_max_size(const struct sshbuf *buf);
/*
* Set the maximum size of buf
* Returns 0 on success, or a negative SSH_ERR_* error code on failure.
*/
int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size);
/*
* Returns the length of data in buf
*/
size_t sshbuf_len(const struct sshbuf *buf);
/*
* Returns number of bytes left in buffer before hitting max_size.
*/
size_t sshbuf_avail(const struct sshbuf *buf);
/*
* Returns a read-only pointer to the start of the data in buf
*/
const u_char *sshbuf_ptr(const struct sshbuf *buf);
/*
* Returns a mutable pointer to the start of the data in buf, or
* NULL if the buffer is read-only.
*/
u_char *sshbuf_mutable_ptr(const struct sshbuf *buf);
/*
* Check whether a reservation of size len will succeed in buf
* Safer to use than direct comparisons again sshbuf_avail as it copes
* with unsigned overflows correctly.
* Returns 0 on success, or a negative SSH_ERR_* error code on failure.
*/
int sshbuf_check_reserve(const struct sshbuf *buf, size_t len);
/*
* Preallocates len additional bytes in buf.
* Useful for cases where the caller knows how many bytes will ultimately be
* required to avoid realloc in the buffer code.
* Returns 0 on success, or a negative SSH_ERR_* error code on failure.
*/
int sshbuf_allocate(struct sshbuf *buf, size_t len);
/*
* Reserve len bytes in buf.
* Returns 0 on success and a pointer to the first reserved byte via the
* optional dpp parameter or a negative * SSH_ERR_* error code on failure.
*/
int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp);
/*
* Consume len bytes from the start of buf
* Returns 0 on success, or a negative SSH_ERR_* error code on failure.
*/
int sshbuf_consume(struct sshbuf *buf, size_t len);
/*
* Consume len bytes from the end of buf
* Returns 0 on success, or a negative SSH_ERR_* error code on failure.
*/
int sshbuf_consume_end(struct sshbuf *buf, size_t len);
/* Extract or deposit some bytes */
int sshbuf_get(struct sshbuf *buf, void *v, size_t len);
int sshbuf_put(struct sshbuf *buf, const void *v, size_t len);
int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v);
/* Append using a printf(3) format */
int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap);
/* Functions to extract or store big-endian words of various sizes */
int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp);
int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp);
int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp);
int sshbuf_get_u8(struct sshbuf *buf, u_char *valp);
int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val);
int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val);
int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val);
int sshbuf_put_u8(struct sshbuf *buf, u_char val);
/*
* Functions to extract or store SSH wire encoded strings (u32 len || data)
* The "cstring" variants admit no \0 characters in the string contents.
* Caller must free *valp.
*/
int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp);
int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp);
int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v);
int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len);
int sshbuf_put_cstring(struct sshbuf *buf, const char *v);
int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v);
/*
* "Direct" variant of sshbuf_get_string, returns pointer into the sshbuf to
* avoid an malloc+memcpy. The pointer is guaranteed to be valid until the
* next sshbuf-modifying function call. Caller does not free.
*/
int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp,
size_t *lenp);
/* Skip past a string */
#define sshbuf_skip_string(buf) sshbuf_get_string_direct(buf, NULL, NULL)
/* Another variant: "peeks" into the buffer without modifying it */
int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
size_t *lenp);
/* XXX peek_u8 / peek_u32 */
/*
* Functions to extract or store SSH wire encoded bignums and elliptic
* curve points.
*/
int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len);
int sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf,
const u_char **valp, size_t *lenp);
#ifdef WITH_OPENSSL
-int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v);
-int sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v);
+int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp);
int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v);
-int sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v);
# ifdef OPENSSL_HAS_ECC
int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g);
int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v);
int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g);
int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v);
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
/* Dump the contents of the buffer in a human-readable format */
void sshbuf_dump(struct sshbuf *buf, FILE *f);
/* Dump specified memory in a human-readable format */
void sshbuf_dump_data(const void *s, size_t len, FILE *f);
/* Return the hexadecimal representation of the contents of the buffer */
char *sshbuf_dtob16(struct sshbuf *buf);
/* Encode the contents of the buffer as base64 */
char *sshbuf_dtob64(struct sshbuf *buf);
/* Decode base64 data and append it to the buffer */
int sshbuf_b64tod(struct sshbuf *buf, const char *b64);
/*
* Duplicate the contents of a buffer to a string (caller to free).
* Returns NULL on buffer error, or if the buffer contains a premature
* nul character.
*/
char *sshbuf_dup_string(struct sshbuf *buf);
/* Macros for decoding/encoding integers */
#define PEEK_U64(p) \
(((u_int64_t)(((const u_char *)(p))[0]) << 56) | \
((u_int64_t)(((const u_char *)(p))[1]) << 48) | \
((u_int64_t)(((const u_char *)(p))[2]) << 40) | \
((u_int64_t)(((const u_char *)(p))[3]) << 32) | \
((u_int64_t)(((const u_char *)(p))[4]) << 24) | \
((u_int64_t)(((const u_char *)(p))[5]) << 16) | \
((u_int64_t)(((const u_char *)(p))[6]) << 8) | \
(u_int64_t)(((const u_char *)(p))[7]))
#define PEEK_U32(p) \
(((u_int32_t)(((const u_char *)(p))[0]) << 24) | \
((u_int32_t)(((const u_char *)(p))[1]) << 16) | \
((u_int32_t)(((const u_char *)(p))[2]) << 8) | \
(u_int32_t)(((const u_char *)(p))[3]))
#define PEEK_U16(p) \
(((u_int16_t)(((const u_char *)(p))[0]) << 8) | \
(u_int16_t)(((const u_char *)(p))[1]))
#define POKE_U64(p, v) \
do { \
const u_int64_t __v = (v); \
((u_char *)(p))[0] = (__v >> 56) & 0xff; \
((u_char *)(p))[1] = (__v >> 48) & 0xff; \
((u_char *)(p))[2] = (__v >> 40) & 0xff; \
((u_char *)(p))[3] = (__v >> 32) & 0xff; \
((u_char *)(p))[4] = (__v >> 24) & 0xff; \
((u_char *)(p))[5] = (__v >> 16) & 0xff; \
((u_char *)(p))[6] = (__v >> 8) & 0xff; \
((u_char *)(p))[7] = __v & 0xff; \
} while (0)
#define POKE_U32(p, v) \
do { \
const u_int32_t __v = (v); \
((u_char *)(p))[0] = (__v >> 24) & 0xff; \
((u_char *)(p))[1] = (__v >> 16) & 0xff; \
((u_char *)(p))[2] = (__v >> 8) & 0xff; \
((u_char *)(p))[3] = __v & 0xff; \
} while (0)
#define POKE_U16(p, v) \
do { \
const u_int16_t __v = (v); \
((u_char *)(p))[0] = (__v >> 8) & 0xff; \
((u_char *)(p))[1] = __v & 0xff; \
} while (0)
/* Internal definitions follow. Exposed for regress tests */
#ifdef SSHBUF_INTERNAL
/*
* Return the allocation size of buf
*/
size_t sshbuf_alloc(const struct sshbuf *buf);
/*
* Increment the reference count of buf.
*/
int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent);
/*
* Return the parent buffer of buf, or NULL if it has no parent.
*/
const struct sshbuf *sshbuf_parent(const struct sshbuf *buf);
/*
* Return the reference count of buf
*/
u_int sshbuf_refcount(const struct sshbuf *buf);
# define SSHBUF_SIZE_INIT 256 /* Initial allocation */
# define SSHBUF_SIZE_INC 256 /* Preferred increment length */
# define SSHBUF_PACK_MIN 8192 /* Minimim packable offset */
/* # define SSHBUF_ABORT abort */
/* # define SSHBUF_DEBUG */
# ifndef SSHBUF_ABORT
# define SSHBUF_ABORT()
# endif
# ifdef SSHBUF_DEBUG
# define SSHBUF_TELL(what) do { \
printf("%s:%d %s: %s size %zu alloc %zu off %zu max %zu\n", \
__FILE__, __LINE__, __func__, what, \
buf->size, buf->alloc, buf->off, buf->max_size); \
fflush(stdout); \
} while (0)
# define SSHBUF_DBG(x) do { \
printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
printf x; \
printf("\n"); \
fflush(stdout); \
} while (0)
# else
# define SSHBUF_TELL(what)
# define SSHBUF_DBG(x)
# endif
#endif /* SSHBUF_INTERNAL */
#endif /* _SSHBUF_H */
diff --git a/sshconnect.c b/sshconnect.c
index 6d819279ee66..fdcdcd85544a 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,1581 +1,1429 @@
-/* $OpenBSD: sshconnect.c,v 1.305 2018/09/20 03:30:44 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.314 2019/02/27 19:37:01 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef HAVE_IFADDRS_H
# include <ifaddrs.h>
#endif
#include "xmalloc.h"
#include "hostfile.h"
#include "ssh.h"
#include "sshbuf.h"
#include "packet.h"
#include "compat.h"
#include "sshkey.h"
#include "sshconnect.h"
#include "hostfile.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "atomicio.h"
#include "dns.h"
#include "monitor_fdpass.h"
#include "ssh2.h"
#include "version.h"
#include "authfile.h"
#include "ssherr.h"
#include "authfd.h"
+#include "kex.h"
-char *client_version_string = NULL;
-char *server_version_string = NULL;
struct sshkey *previous_host_key = NULL;
static int matching_host_key_dns = 0;
static pid_t proxy_command_pid = 0;
/* import */
+extern int debug_flag;
extern Options options;
extern char *__progname;
static int show_other_keys(struct hostkeys *, struct sshkey *);
static void warn_changed_key(struct sshkey *);
/* Expand a proxy command */
static char *
expand_proxy_command(const char *proxy_command, const char *user,
const char *host, int port)
{
char *tmp, *ret, strport[NI_MAXSERV];
snprintf(strport, sizeof strport, "%d", port);
xasprintf(&tmp, "exec %s", proxy_command);
ret = percent_expand(tmp, "h", host, "p", strport,
"r", options.user, (char *)NULL);
free(tmp);
return ret;
}
+static void
+stderr_null(void)
+{
+ int devnull;
+
+ if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
+ error("Can't open %s for stderr redirection: %s",
+ _PATH_DEVNULL, strerror(errno));
+ return;
+ }
+ if (devnull == STDERR_FILENO)
+ return;
+ if (dup2(devnull, STDERR_FILENO) == -1)
+ error("Cannot redirect stderr to %s", _PATH_DEVNULL);
+ if (devnull > STDERR_FILENO)
+ close(devnull);
+}
+
/*
* Connect to the given ssh server using a proxy command that passes a
* a connected fd back to us.
*/
static int
ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, u_short port,
const char *proxy_command)
{
char *command_string;
int sp[2], sock;
pid_t pid;
char *shell;
if ((shell = getenv("SHELL")) == NULL)
shell = _PATH_BSHELL;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) < 0)
fatal("Could not create socketpair to communicate with "
"proxy dialer: %.100s", strerror(errno));
command_string = expand_proxy_command(proxy_command, options.user,
host, port);
debug("Executing proxy dialer command: %.500s", command_string);
/* Fork and execute the proxy command. */
if ((pid = fork()) == 0) {
char *argv[10];
close(sp[1]);
/* Redirect stdin and stdout. */
if (sp[0] != 0) {
if (dup2(sp[0], 0) < 0)
perror("dup2 stdin");
}
if (sp[0] != 1) {
if (dup2(sp[0], 1) < 0)
perror("dup2 stdout");
}
if (sp[0] >= 2)
close(sp[0]);
/*
- * Stderr is left as it is so that error messages get
- * printed on the user's terminal.
+ * Stderr is left for non-ControlPersist connections is so
+ * error messages may be printed on the user's terminal.
*/
+ if (!debug_flag && options.control_path != NULL &&
+ options.control_persist)
+ stderr_null();
+
argv[0] = shell;
argv[1] = "-c";
argv[2] = command_string;
argv[3] = NULL;
/*
* Execute the proxy command.
* Note that we gave up any extra privileges above.
*/
execv(argv[0], argv);
perror(argv[0]);
exit(1);
}
/* Parent. */
if (pid < 0)
fatal("fork failed: %.100s", strerror(errno));
close(sp[0]);
free(command_string);
if ((sock = mm_receive_fd(sp[1])) == -1)
fatal("proxy dialer did not pass back a connection");
close(sp[1]);
while (waitpid(pid, NULL, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for child: %s", strerror(errno));
/* Set the connection file descriptors. */
if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0;
}
/*
* Connect to the given ssh server using a proxy command.
*/
static int
ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port,
const char *proxy_command)
{
char *command_string;
int pin[2], pout[2];
pid_t pid;
char *shell;
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
/* Create pipes for communicating with the proxy. */
if (pipe(pin) < 0 || pipe(pout) < 0)
fatal("Could not create pipes to communicate with the proxy: %.100s",
strerror(errno));
command_string = expand_proxy_command(proxy_command, options.user,
host, port);
debug("Executing proxy command: %.500s", command_string);
/* Fork and execute the proxy command. */
if ((pid = fork()) == 0) {
char *argv[10];
/* Redirect stdin and stdout. */
close(pin[1]);
if (pin[0] != 0) {
if (dup2(pin[0], 0) < 0)
perror("dup2 stdin");
close(pin[0]);
}
close(pout[0]);
if (dup2(pout[1], 1) < 0)
perror("dup2 stdout");
/* Cannot be 1 because pin allocated two descriptors. */
close(pout[1]);
- /* Stderr is left as it is so that error messages get
- printed on the user's terminal. */
+ /*
+ * Stderr is left for non-ControlPersist connections is so
+ * error messages may be printed on the user's terminal.
+ */
+ if (!debug_flag && options.control_path != NULL &&
+ options.control_persist)
+ stderr_null();
+
argv[0] = shell;
argv[1] = "-c";
argv[2] = command_string;
argv[3] = NULL;
/* Execute the proxy command. Note that we gave up any
extra privileges above. */
signal(SIGPIPE, SIG_DFL);
execv(argv[0], argv);
perror(argv[0]);
exit(1);
}
/* Parent. */
if (pid < 0)
fatal("fork failed: %.100s", strerror(errno));
else
proxy_command_pid = pid; /* save pid to clean up later */
/* Close child side of the descriptors. */
close(pin[0]);
close(pout[1]);
/* Free the command name. */
free(command_string);
/* Set the connection file descriptors. */
if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0;
}
void
ssh_kill_proxy_command(void)
{
/*
* Send SIGHUP to proxy command if used. We don't wait() in
* case it hangs and instead rely on init to reap the child
*/
if (proxy_command_pid > 1)
kill(proxy_command_pid, SIGHUP);
}
#ifdef HAVE_IFADDRS_H
/*
* Search a interface address list (returned from getifaddrs(3)) for an
* address that matches the desired address family on the specified interface.
* Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure.
*/
static int
check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
struct sockaddr_storage *resultp, socklen_t *rlenp)
{
struct sockaddr_in6 *sa6;
struct sockaddr_in *sa;
struct in6_addr *v6addr;
const struct ifaddrs *ifa;
int allow_local;
/*
* Prefer addresses that are not loopback or linklocal, but use them
* if nothing else matches.
*/
for (allow_local = 0; allow_local < 2; allow_local++) {
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
(ifa->ifa_flags & IFF_UP) == 0 ||
ifa->ifa_addr->sa_family != af ||
strcmp(ifa->ifa_name, options.bind_interface) != 0)
continue;
switch (ifa->ifa_addr->sa_family) {
case AF_INET:
sa = (struct sockaddr_in *)ifa->ifa_addr;
if (!allow_local && sa->sin_addr.s_addr ==
htonl(INADDR_LOOPBACK))
continue;
if (*rlenp < sizeof(struct sockaddr_in)) {
error("%s: v4 addr doesn't fit",
__func__);
return -1;
}
*rlenp = sizeof(struct sockaddr_in);
memcpy(resultp, sa, *rlenp);
return 0;
case AF_INET6:
sa6 = (struct sockaddr_in6 *)ifa->ifa_addr;
v6addr = &sa6->sin6_addr;
if (!allow_local &&
(IN6_IS_ADDR_LINKLOCAL(v6addr) ||
IN6_IS_ADDR_LOOPBACK(v6addr)))
continue;
if (*rlenp < sizeof(struct sockaddr_in6)) {
error("%s: v6 addr doesn't fit",
__func__);
return -1;
}
*rlenp = sizeof(struct sockaddr_in6);
memcpy(resultp, sa6, *rlenp);
return 0;
}
}
}
return -1;
}
#endif
/*
* Creates a socket for use as the ssh connection.
*/
static int
ssh_create_socket(struct addrinfo *ai)
{
int sock, r;
struct sockaddr_storage bindaddr;
socklen_t bindaddrlen = 0;
struct addrinfo hints, *res = NULL;
#ifdef HAVE_IFADDRS_H
struct ifaddrs *ifaddrs = NULL;
#endif
char ntop[NI_MAXHOST];
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0) {
error("socket: %s", strerror(errno));
return -1;
}
fcntl(sock, F_SETFD, FD_CLOEXEC);
/* Bind the socket to an alternative local IP address */
if (options.bind_address == NULL && options.bind_interface == NULL)
return sock;
if (options.bind_address != NULL) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = ai->ai_family;
hints.ai_socktype = ai->ai_socktype;
hints.ai_protocol = ai->ai_protocol;
hints.ai_flags = AI_PASSIVE;
if ((r = getaddrinfo(options.bind_address, NULL,
&hints, &res)) != 0) {
error("getaddrinfo: %s: %s", options.bind_address,
ssh_gai_strerror(r));
goto fail;
}
if (res == NULL) {
error("getaddrinfo: no addrs");
goto fail;
}
- if (res->ai_addrlen > sizeof(bindaddr)) {
- error("%s: addr doesn't fit", __func__);
- goto fail;
- }
memcpy(&bindaddr, res->ai_addr, res->ai_addrlen);
bindaddrlen = res->ai_addrlen;
} else if (options.bind_interface != NULL) {
#ifdef HAVE_IFADDRS_H
if ((r = getifaddrs(&ifaddrs)) != 0) {
error("getifaddrs: %s: %s", options.bind_interface,
strerror(errno));
goto fail;
}
bindaddrlen = sizeof(bindaddr);
if (check_ifaddrs(options.bind_interface, ai->ai_family,
ifaddrs, &bindaddr, &bindaddrlen) != 0) {
logit("getifaddrs: %s: no suitable addresses",
options.bind_interface);
goto fail;
}
#else
error("BindInterface not supported on this platform.");
#endif
}
if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen,
ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) {
error("%s: getnameinfo failed: %s", __func__,
ssh_gai_strerror(r));
goto fail;
}
if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) {
error("bind %s: %s", ntop, strerror(errno));
goto fail;
}
debug("%s: bound to %s", __func__, ntop);
/* success */
goto out;
fail:
close(sock);
sock = -1;
out:
if (res != NULL)
freeaddrinfo(res);
#ifdef HAVE_IFADDRS_H
if (ifaddrs != NULL)
freeifaddrs(ifaddrs);
#endif
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.
* The address of the remote host will be returned in hostaddr.
* If port is 0, the default port will be used.
* Connection_attempts specifies the maximum number of tries (one per
* second). If proxy_command is non-NULL, it specifies the command (with %h
* and %p substituted for host and port, respectively) to use to contact
* the daemon.
*/
static int
ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
struct sockaddr_storage *hostaddr, u_short port, int family,
int connection_attempts, int *timeout_ms, int want_keepalive)
{
- int on = 1;
+ int on = 1, saved_timeout_ms = *timeout_ms;
int oerrno, sock = -1, attempt;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
struct addrinfo *ai;
debug2("%s", __func__);
memset(ntop, 0, sizeof(ntop));
memset(strport, 0, sizeof(strport));
for (attempt = 0; attempt < connection_attempts; attempt++) {
if (attempt > 0) {
/* Sleep a moment before retrying. */
sleep(1);
debug("Trying again...");
}
/*
* Loop through addresses for this host, and try each one in
* sequence until the connection succeeds.
*/
for (ai = aitop; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET &&
ai->ai_family != AF_INET6) {
errno = EAFNOSUPPORT;
continue;
}
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
oerrno = errno;
error("%s: getnameinfo failed", __func__);
errno = oerrno;
continue;
}
debug("Connecting to %.200s [%.100s] port %s.",
host, ntop, strport);
/* Create a socket for connecting. */
sock = ssh_create_socket(ai);
if (sock < 0) {
/* Any error is already output */
errno = 0;
continue;
}
+ *timeout_ms = saved_timeout_ms;
if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,
timeout_ms) >= 0) {
/* Successful connection. */
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
break;
} else {
oerrno = errno;
debug("connect to address %s port %s: %s",
ntop, strport, strerror(errno));
close(sock);
sock = -1;
errno = oerrno;
}
}
if (sock != -1)
break; /* Successful connection. */
}
/* Return failure if we didn't get a successful connection. */
if (sock == -1) {
error("ssh: connect to host %s port %s: %s",
host, strport, errno == 0 ? "failure" : strerror(errno));
return -1;
}
debug("Connection established.");
/* Set SO_KEEPALIVE if requested. */
if (want_keepalive &&
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
sizeof(on)) < 0)
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
/* Set the connection. */
if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0;
}
int
ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs,
struct sockaddr_storage *hostaddr, u_short port, int family,
int connection_attempts, int *timeout_ms, int want_keepalive)
{
+ int in, out;
+
if (options.proxy_command == NULL) {
return ssh_connect_direct(ssh, host, addrs, hostaddr, port,
family, connection_attempts, timeout_ms, want_keepalive);
} else if (strcmp(options.proxy_command, "-") == 0) {
- if ((ssh_packet_set_connection(ssh,
- STDIN_FILENO, STDOUT_FILENO)) == NULL)
+ if ((in = dup(STDIN_FILENO)) < 0 ||
+ (out = dup(STDOUT_FILENO)) < 0) {
+ if (in >= 0)
+ close(in);
+ error("%s: dup() in/out failed", __func__);
+ return -1; /* ssh_packet_set_connection logs error */
+ }
+ if ((ssh_packet_set_connection(ssh, in, out)) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0;
} else if (options.proxy_use_fdpass) {
return ssh_proxy_fdpass_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' */
static int
-confirm(const char *prompt)
+confirm(const char *prompt, const char *fingerprint)
{
const char *msg, *again = "Please type 'yes' or 'no': ";
+ const char *again_fp = "Please type 'yes', 'no' or the fingerprint: ";
char *p;
int ret = -1;
if (options.batch_mode)
return 0;
- for (msg = prompt;;msg = again) {
+ for (msg = prompt;;msg = fingerprint ? again_fp : again) {
p = read_passphrase(msg, RP_ECHO);
if (p == NULL)
return 0;
p[strcspn(p, "\n")] = '\0';
if (p[0] == '\0' || strcasecmp(p, "no") == 0)
ret = 0;
- else if (strcasecmp(p, "yes") == 0)
+ else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL &&
+ strcasecmp(p, fingerprint) == 0))
ret = 1;
free(p);
if (ret != -1)
return ret;
}
}
static int
check_host_cert(const char *host, const struct sshkey *key)
{
const char *reason;
int r;
if (sshkey_cert_check_authority(key, 1, 0, host, &reason) != 0) {
error("%s", reason);
return 0;
}
if (sshbuf_len(key->cert->critical) != 0) {
error("Certificate for %s contains unsupported "
"critical options(s)", host);
return 0;
}
if ((r = sshkey_check_cert_sigtype(key,
options.ca_sign_algorithms)) != 0) {
logit("%s: certificate signature algorithm %s: %s", __func__,
(key->cert == NULL || key->cert->signature_type == NULL) ?
"(null)" : key->cert->signature_type, ssh_err(r));
return 0;
}
return 1;
}
static int
sockaddr_is_local(struct sockaddr *hostaddr)
{
switch (hostaddr->sa_family) {
case AF_INET:
return (ntohl(((struct sockaddr_in *)hostaddr)->
sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
case AF_INET6:
return IN6_IS_ADDR_LOOPBACK(
&(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
default:
return 0;
}
}
/*
* Prepare the hostname and ip address strings that are used to lookup
* host keys in known_hosts files. These may have a port number appended.
*/
void
get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
u_short port, char **hostfile_hostname, char **hostfile_ipaddr)
{
char ntop[NI_MAXHOST];
socklen_t addrlen;
switch (hostaddr == NULL ? -1 : hostaddr->sa_family) {
case -1:
addrlen = 0;
break;
case AF_INET:
addrlen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
addrlen = sizeof(struct sockaddr_in6);
break;
default:
addrlen = sizeof(struct sockaddr);
break;
}
/*
* We don't have the remote ip-address for connections
* using a proxy command
*/
if (hostfile_ipaddr != NULL) {
if (options.proxy_command == NULL) {
if (getnameinfo(hostaddr, addrlen,
ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
fatal("%s: getnameinfo failed", __func__);
*hostfile_ipaddr = put_host_port(ntop, port);
} else {
*hostfile_ipaddr = xstrdup("<no hostip for proxy "
"command>");
}
}
/*
* Allow the user to record the key under a different name or
* differentiate a non-standard port. This is useful for ssh
* tunneling over forwarded connections or if you run multiple
* sshd's on different ports on the same machine.
*/
if (hostfile_hostname != NULL) {
if (options.host_key_alias != NULL) {
*hostfile_hostname = xstrdup(options.host_key_alias);
debug("using hostkeyalias: %s", *hostfile_hostname);
} else {
*hostfile_hostname = put_host_port(hostname, port);
}
}
}
/*
* check whether the supplied host key is valid, return -1 if the key
* is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
*/
#define RDRW 0
#define RDONLY 1
#define ROQUIET 2
static int
check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
struct sshkey *host_key, int readonly,
char **user_hostfiles, u_int num_user_hostfiles,
char **system_hostfiles, u_int num_system_hostfiles)
{
HostStatus host_status;
HostStatus ip_status;
struct sshkey *raw_key = NULL;
char *ip = NULL, *host = NULL;
char hostline[1000], *hostp, *fp, *ra;
char msg[1024];
const char *type;
const struct hostkey_entry *host_found, *ip_found;
- int len, cancelled_forwarding = 0;
+ int len, cancelled_forwarding = 0, confirmed;
int local = sockaddr_is_local(hostaddr);
int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0;
int hostkey_trusted = 0; /* Known or explicitly accepted by user */
struct hostkeys *host_hostkeys, *ip_hostkeys;
u_int i;
/*
* Force accepting of the host key for loopback/localhost. The
* problem is that if the home directory is NFS-mounted to multiple
* machines, localhost will refer to a different machine in each of
* them, and the user will get bogus HOST_CHANGED warnings. This
* essentially disables host authentication for localhost; however,
* this is probably not a real problem.
*/
if (options.no_host_authentication_for_localhost == 1 && local &&
options.host_key_alias == NULL) {
debug("Forcing accepting of host key for "
"loopback/localhost.");
return 0;
}
/*
* Prepare the hostname and address strings used for hostkey lookup.
* In some cases, these will have a port number appended.
*/
get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip);
/*
* Turn off check_host_ip if the connection is to localhost, via proxy
* command or if we don't have a hostname to compare with
*/
if (options.check_host_ip && (local ||
strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
options.check_host_ip = 0;
host_hostkeys = init_hostkeys();
for (i = 0; i < num_user_hostfiles; i++)
load_hostkeys(host_hostkeys, host, user_hostfiles[i]);
for (i = 0; i < num_system_hostfiles; i++)
load_hostkeys(host_hostkeys, host, system_hostfiles[i]);
ip_hostkeys = NULL;
if (!want_cert && options.check_host_ip) {
ip_hostkeys = init_hostkeys();
for (i = 0; i < num_user_hostfiles; i++)
load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]);
for (i = 0; i < num_system_hostfiles; i++)
load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]);
}
retry:
/* Reload these as they may have changed on cert->key downgrade */
want_cert = sshkey_is_cert(host_key);
type = sshkey_type(host_key);
/*
* Check if the host key is present in the user's list of known
* hosts or in the systemwide list.
*/
host_status = check_key_in_hostkeys(host_hostkeys, host_key,
&host_found);
/*
* Also perform check for the ip address, skip the check if we are
* localhost, looking for a certificate, or the hostname was an ip
* address to begin with.
*/
if (!want_cert && ip_hostkeys != NULL) {
ip_status = check_key_in_hostkeys(ip_hostkeys, host_key,
&ip_found);
if (host_status == HOST_CHANGED &&
(ip_status != HOST_CHANGED ||
(ip_found != NULL &&
!sshkey_equal(ip_found->key, host_found->key))))
host_ip_differ = 1;
} else
ip_status = host_status;
switch (host_status) {
case HOST_OK:
/* The host is known and the key matches. */
debug("Host '%.200s' is known and matches the %s host %s.",
host, type, want_cert ? "certificate" : "key");
debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
host_found->file, host_found->line);
if (want_cert &&
!check_host_cert(options.host_key_alias == NULL ?
hostname : options.host_key_alias, host_key))
goto fail;
if (options.check_host_ip && ip_status == HOST_NEW) {
if (readonly || want_cert)
logit("%s host key for IP address "
"'%.128s' not in list of known hosts.",
type, ip);
else if (!add_host_to_hostfile(user_hostfiles[0], ip,
host_key, options.hash_known_hosts))
logit("Failed to add the %s host key for IP "
"address '%.128s' to the list of known "
"hosts (%.500s).", type, ip,
user_hostfiles[0]);
else
logit("Warning: Permanently added the %s host "
"key for IP address '%.128s' to the list "
"of known hosts.", type, ip);
} else if (options.visual_host_key) {
fp = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
logit("Host key fingerprint is %s\n%s", fp, ra);
free(ra);
free(fp);
}
hostkey_trusted = 1;
break;
case HOST_NEW:
if (options.host_key_alias == NULL && port != 0 &&
port != SSH_DEFAULT_PORT) {
debug("checking without port identifier");
if (check_host_key(hostname, hostaddr, 0, host_key,
ROQUIET, user_hostfiles, num_user_hostfiles,
system_hostfiles, num_system_hostfiles) == 0) {
debug("found matching key w/out port");
break;
}
}
if (readonly || want_cert)
goto fail;
/* The host is new. */
if (options.strict_host_key_checking ==
SSH_STRICT_HOSTKEY_YES) {
/*
* User has requested strict host key checking. We
* will not add the host key automatically. The only
* alternative left is to abort.
*/
error("No %s host key is known for %.200s and you "
"have requested strict checking.", type, host);
goto fail;
} else if (options.strict_host_key_checking ==
SSH_STRICT_HOSTKEY_ASK) {
char msg1[1024], msg2[1024];
if (show_other_keys(host_hostkeys, host_key))
snprintf(msg1, sizeof(msg1),
"\nbut keys of different type are already"
" known for this host.");
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
fp = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
snprintf(msg2, sizeof(msg2),
"Matching host key fingerprint"
" found in DNS.\n");
else
snprintf(msg2, sizeof(msg2),
"No matching host key fingerprint"
" found in DNS.\n");
}
snprintf(msg, sizeof(msg),
"The authenticity of host '%.200s (%s)' can't be "
"established%s\n"
"%s key fingerprint is %s.%s%s\n%s"
"Are you sure you want to continue connecting "
- "(yes/no)? ",
+ "(yes/no/[fingerprint])? ",
host, ip, msg1, type, fp,
options.visual_host_key ? "\n" : "",
options.visual_host_key ? ra : "",
msg2);
free(ra);
+ confirmed = confirm(msg, fp);
free(fp);
- if (!confirm(msg))
+ if (!confirmed)
goto fail;
hostkey_trusted = 1; /* user explicitly confirmed */
}
/*
* If in "new" or "off" strict mode, add the key automatically
* to the local known_hosts file.
*/
if (options.check_host_ip && ip_status == HOST_NEW) {
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
hostp = hostline;
if (options.hash_known_hosts) {
/* Add hash of host and IP separately */
r = add_host_to_hostfile(user_hostfiles[0],
host, host_key, options.hash_known_hosts) &&
add_host_to_hostfile(user_hostfiles[0], ip,
host_key, options.hash_known_hosts);
} else {
/* Add unhashed "host,ip" */
r = add_host_to_hostfile(user_hostfiles[0],
hostline, host_key,
options.hash_known_hosts);
}
} else {
r = add_host_to_hostfile(user_hostfiles[0], host,
host_key, options.hash_known_hosts);
hostp = host;
}
if (!r)
logit("Failed to add the host to the list of known "
"hosts (%.500s).", user_hostfiles[0]);
else
logit("Warning: Permanently added '%.200s' (%s) to the "
"list of known hosts.", hostp, type);
break;
case HOST_REVOKED:
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REVOKED HOST KEY DETECTED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("The %s host key for %s is marked as revoked.", type, host);
error("This could mean that a stolen key is being used to");
error("impersonate this host.");
/*
* If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort.
*/
if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
error("%s host key for %.200s was revoked and you have "
"requested strict checking.", type, host);
goto fail;
}
goto continue_unsafe;
case HOST_CHANGED:
if (want_cert) {
/*
* This is only a debug() since it is valid to have
* CAs with wildcard DNS matches that don't match
* all hosts that one might visit.
*/
debug("Host certificate authority does not "
"match %s in %s:%lu", CA_MARKER,
host_found->file, host_found->line);
goto fail;
}
if (readonly == ROQUIET)
goto fail;
if (options.check_host_ip && host_ip_differ) {
char *key_msg;
if (ip_status == HOST_NEW)
key_msg = "is unknown";
else if (ip_status == HOST_OK)
key_msg = "is unchanged";
else
key_msg = "has a different value";
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("The %s host key for %s has changed,", type, host);
error("and the key for the corresponding IP address %s", ip);
error("%s. This could either mean that", key_msg);
error("DNS SPOOFING is happening or the IP address for the host");
error("and its host key have changed at the same time.");
if (ip_status != HOST_NEW)
error("Offending key for IP in %s:%lu",
ip_found->file, ip_found->line);
}
/* The host key has changed. */
warn_changed_key(host_key);
error("Add correct host key in %.100s to get rid of this message.",
user_hostfiles[0]);
error("Offending %s key in %s:%lu",
sshkey_type(host_found->key),
host_found->file, host_found->line);
/*
* If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort.
*/
if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
error("%s host key for %.200s has changed and you have "
"requested strict checking.", type, host);
goto fail;
}
continue_unsafe:
/*
* If strict host key checking has not been requested, allow
* the connection but without MITM-able authentication or
* forwarding.
*/
if (options.password_authentication) {
error("Password authentication is disabled to avoid "
"man-in-the-middle attacks.");
options.password_authentication = 0;
cancelled_forwarding = 1;
}
if (options.kbd_interactive_authentication) {
error("Keyboard-interactive authentication is disabled"
" to avoid man-in-the-middle attacks.");
options.kbd_interactive_authentication = 0;
options.challenge_response_authentication = 0;
cancelled_forwarding = 1;
}
if (options.challenge_response_authentication) {
error("Challenge/response authentication is disabled"
" to avoid man-in-the-middle attacks.");
options.challenge_response_authentication = 0;
cancelled_forwarding = 1;
}
if (options.forward_agent) {
error("Agent forwarding is disabled to avoid "
"man-in-the-middle attacks.");
options.forward_agent = 0;
cancelled_forwarding = 1;
}
if (options.forward_x11) {
error("X11 forwarding is disabled to avoid "
"man-in-the-middle attacks.");
options.forward_x11 = 0;
cancelled_forwarding = 1;
}
if (options.num_local_forwards > 0 ||
options.num_remote_forwards > 0) {
error("Port forwarding is disabled to avoid "
"man-in-the-middle attacks.");
options.num_local_forwards =
options.num_remote_forwards = 0;
cancelled_forwarding = 1;
}
if (options.tun_open != SSH_TUNMODE_NO) {
error("Tunnel forwarding is disabled to avoid "
"man-in-the-middle attacks.");
options.tun_open = SSH_TUNMODE_NO;
cancelled_forwarding = 1;
}
if (options.exit_on_forward_failure && cancelled_forwarding)
fatal("Error: forwarding disabled due to host key "
"check failure");
/*
* XXX Should permit the user to change to use the new id.
* This could be done by converting the host key to an
* identifying sentence, tell that the host identifies itself
* by that sentence, and ask the user if he/she wishes to
* accept the authentication.
*/
break;
case HOST_FOUND:
fatal("internal error");
break;
}
if (options.check_host_ip && host_status != HOST_CHANGED &&
ip_status == HOST_CHANGED) {
snprintf(msg, sizeof(msg),
"Warning: the %s host key for '%.200s' "
"differs from the key for the IP address '%.128s'"
"\nOffending key for IP in %s:%lu",
type, host, ip, ip_found->file, ip_found->line);
if (host_status == HOST_OK) {
len = strlen(msg);
snprintf(msg + len, sizeof(msg) - len,
"\nMatching host key in %s:%lu",
host_found->file, host_found->line);
}
if (options.strict_host_key_checking ==
SSH_STRICT_HOSTKEY_ASK) {
strlcat(msg, "\nAre you sure you want "
"to continue connecting (yes/no)? ", sizeof(msg));
- if (!confirm(msg))
+ if (!confirm(msg, NULL))
goto fail;
} else if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
logit("%s", msg);
error("Exiting, you have requested strict checking.");
goto fail;
} else {
logit("%s", msg);
}
}
if (!hostkey_trusted && options.update_hostkeys) {
debug("%s: hostkey not known or explicitly trusted: "
"disabling UpdateHostkeys", __func__);
options.update_hostkeys = 0;
}
free(ip);
free(host);
if (host_hostkeys != NULL)
free_hostkeys(host_hostkeys);
if (ip_hostkeys != NULL)
free_hostkeys(ip_hostkeys);
return 0;
fail:
if (want_cert && host_status != HOST_REVOKED) {
/*
* No matching certificate. Downgrade cert to raw key and
* search normally.
*/
debug("No matching CA found. Retry with plain key");
if ((r = sshkey_from_private(host_key, &raw_key)) != 0)
fatal("%s: sshkey_from_private: %s",
__func__, ssh_err(r));
if ((r = sshkey_drop_cert(raw_key)) != 0)
fatal("Couldn't drop certificate: %s", ssh_err(r));
host_key = raw_key;
goto retry;
}
sshkey_free(raw_key);
free(ip);
free(host);
if (host_hostkeys != NULL)
free_hostkeys(host_hostkeys);
if (ip_hostkeys != NULL)
free_hostkeys(ip_hostkeys);
return -1;
}
/* returns 0 if key verifies or -1 if key does NOT verify */
int
verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
{
u_int i;
int r = -1, flags = 0;
char valid[64], *fp = NULL, *cafp = NULL;
struct sshkey *plain = NULL;
if ((fp = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
error("%s: fingerprint host key: %s", __func__, ssh_err(r));
r = -1;
goto out;
}
if (sshkey_is_cert(host_key)) {
if ((cafp = sshkey_fingerprint(host_key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
error("%s: fingerprint CA key: %s",
__func__, ssh_err(r));
r = -1;
goto out;
}
sshkey_format_cert_validity(host_key->cert,
valid, sizeof(valid));
debug("Server host certificate: %s %s, serial %llu "
"ID \"%s\" CA %s %s valid %s",
sshkey_ssh_name(host_key), fp,
(unsigned long long)host_key->cert->serial,
host_key->cert->key_id,
sshkey_ssh_name(host_key->cert->signature_key), cafp,
valid);
for (i = 0; i < host_key->cert->nprincipals; i++) {
debug2("Server host certificate hostname: %s",
host_key->cert->principals[i]);
}
} else {
debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp);
}
if (sshkey_equal(previous_host_key, host_key)) {
debug2("%s: server host key %s %s matches cached key",
__func__, sshkey_type(host_key), fp);
r = 0;
goto out;
}
/* Check in RevokedHostKeys file if specified */
if (options.revoked_host_keys != NULL) {
r = sshkey_check_revoked(host_key, options.revoked_host_keys);
switch (r) {
case 0:
break; /* not revoked */
case SSH_ERR_KEY_REVOKED:
error("Host key %s %s revoked by file %s",
sshkey_type(host_key), fp,
options.revoked_host_keys);
r = -1;
goto out;
default:
error("Error checking host key %s %s in "
"revoked keys file %s: %s", sshkey_type(host_key),
fp, options.revoked_host_keys, ssh_err(r));
r = -1;
goto out;
}
}
if (options.verify_host_key_dns) {
/*
* XXX certs are not yet supported for DNS, so downgrade
* them and try the plain key.
*/
if ((r = sshkey_from_private(host_key, &plain)) != 0)
goto out;
if (sshkey_is_cert(plain))
sshkey_drop_cert(plain);
if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
if (flags & DNS_VERIFY_FOUND) {
if (options.verify_host_key_dns == 1 &&
flags & DNS_VERIFY_MATCH &&
flags & DNS_VERIFY_SECURE) {
r = 0;
goto out;
}
if (flags & DNS_VERIFY_MATCH) {
matching_host_key_dns = 1;
} else {
warn_changed_key(plain);
error("Update the SSHFP RR in DNS "
"with the new host key to get rid "
"of this message.");
}
}
}
}
r = check_host_key(host, hostaddr, options.port, host_key, RDRW,
options.user_hostfiles, options.num_user_hostfiles,
options.system_hostfiles, options.num_system_hostfiles);
out:
sshkey_free(plain);
free(fp);
free(cafp);
if (r == 0 && host_key != NULL) {
sshkey_free(previous_host_key);
r = sshkey_from_private(host_key, &previous_host_key);
}
return r;
}
/*
* Starts a dialog with the server, and authenticates the current user on the
* server. This does not need any extra privileges. The basic connection
* to the server must already have been established before this is called.
* If login fails, this function prints an error and never returns.
* This function does not require super-user privileges.
*/
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)
{
char *host;
char *server_user, *local_user;
local_user = xstrdup(pw->pw_name);
server_user = options.user ? options.user : local_user;
/* Convert the user-supplied hostname into all lowercase. */
host = xstrdup(orighost);
lowercase(host);
/* 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. */
- packet_set_nonblocking();
+ ssh_packet_set_nonblocking(ssh);
/* key exchange */
/* authenticate user */
debug("Authenticating to %s:%d as '%s'", host, port, server_user);
- ssh_kex2(host, hostaddr, port);
- ssh_userauth2(local_user, server_user, host, sensitive);
+ ssh_kex2(ssh, host, hostaddr, port);
+ ssh_userauth2(ssh, local_user, server_user, host, sensitive);
free(local_user);
}
-void
-ssh_put_password(char *password)
-{
- int size;
- char *padded;
-
- if (datafellows & SSH_BUG_PASSWORDPAD) {
- packet_put_cstring(password);
- return;
- }
- size = ROUNDUP(strlen(password) + 1, 32);
- padded = xcalloc(1, size);
- strlcpy(padded, password, size);
- packet_put_string(padded, size);
- explicit_bzero(padded, size);
- free(padded);
-}
-
/* print all known host keys for a given host, but skip keys of given type */
static int
show_other_keys(struct hostkeys *hostkeys, struct sshkey *key)
{
int type[] = {
KEY_RSA,
KEY_DSA,
KEY_ECDSA,
KEY_ED25519,
KEY_XMSS,
-1
};
int i, ret = 0;
char *fp, *ra;
const struct hostkey_entry *found;
for (i = 0; type[i] != -1; i++) {
if (type[i] == key->type)
continue;
if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
continue;
fp = sshkey_fingerprint(found->key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = sshkey_fingerprint(found->key,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
sshkey_type(found->key),
found->host, found->file, found->line,
sshkey_type(found->key), fp);
if (options.visual_host_key)
logit("%s", ra);
free(ra);
free(fp);
ret = 1;
}
return ret;
}
static void
warn_changed_key(struct sshkey *host_key)
{
char *fp;
fp = sshkey_fingerprint(host_key, options.fingerprint_hash,
SSH_FP_DEFAULT);
if (fp == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
error("It is also possible that a host key has just been changed.");
error("The fingerprint for the %s key sent by the remote host is\n%s.",
sshkey_type(host_key), fp);
error("Please contact your system administrator.");
free(fp);
}
/*
* Execute a local command
*/
int
ssh_local_cmd(const char *args)
{
char *shell;
pid_t pid;
int status;
void (*osighand)(int);
if (!options.permit_local_command ||
args == NULL || !*args)
return (1);
if ((shell = getenv("SHELL")) == NULL || *shell == '\0')
shell = _PATH_BSHELL;
osighand = signal(SIGCHLD, SIG_DFL);
pid = fork();
if (pid == 0) {
signal(SIGPIPE, SIG_DFL);
debug3("Executing %s -c \"%s\"", shell, args);
execl(shell, shell, "-c", args, (char *)NULL);
error("Couldn't execute %s -c \"%s\": %s",
shell, args, strerror(errno));
_exit(1);
} else if (pid == -1)
fatal("fork failed: %.100s", strerror(errno));
while (waitpid(pid, &status, 0) == -1)
if (errno != EINTR)
fatal("Couldn't wait for child: %s", strerror(errno));
signal(SIGCHLD, osighand);
if (!WIFEXITED(status))
return (1);
return (WEXITSTATUS(status));
}
void
maybe_add_key_to_agent(char *authfile, const struct sshkey *private,
char *comment, char *passphrase)
{
int auth_sock = -1, r;
if (options.add_keys_to_agent == 0)
return;
if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
debug3("no authentication agent, not adding key");
return;
}
if (options.add_keys_to_agent == 2 &&
!ask_permission("Add key %s (%s) to agent?", authfile, comment)) {
debug3("user denied adding this key");
close(auth_sock);
return;
}
if ((r = ssh_add_identity_constrained(auth_sock, private, comment, 0,
(options.add_keys_to_agent == 3), 0)) == 0)
debug("identity added to agent: %s", authfile);
else
debug("could not add identity to agent: %s (%d)", authfile, r);
close(auth_sock);
}
diff --git a/sshconnect.h b/sshconnect.h
index 890d857330cd..6e8989b27b80 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,59 +1,55 @@
-/* $OpenBSD: sshconnect.h,v 1.35 2018/07/19 10:28:47 dtucker Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.37 2019/01/19 21:36:38 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
typedef struct Sensitive Sensitive;
struct Sensitive {
struct sshkey **keys;
int nkeys;
};
struct addrinfo;
struct ssh;
int ssh_connect(struct ssh *, const char *, struct addrinfo *,
struct sockaddr_storage *, u_short, int, int, int *, int);
void ssh_kill_proxy_command(void);
-void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short,
- struct passwd *, int);
-
-void ssh_exchange_identification(int);
+void ssh_login(struct ssh *, Sensitive *, const char *,
+ struct sockaddr *, u_short, struct passwd *, int);
int verify_host_key(char *, struct sockaddr *, struct sshkey *);
void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
char **, char **);
-void ssh_kex(char *, struct sockaddr *);
-void ssh_kex2(char *, struct sockaddr *, u_short);
+void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short);
-void ssh_userauth1(const char *, const char *, char *, Sensitive *);
-void ssh_userauth2(const char *, const char *, char *, Sensitive *);
+void ssh_userauth2(struct ssh *ssh, const char *, const char *,
+ char *, Sensitive *);
-void ssh_put_password(char *);
int ssh_local_cmd(const char *);
void maybe_add_key_to_agent(char *, const struct sshkey *, char *, char *);
diff --git a/sshconnect2.c b/sshconnect2.c
index 1675f393561e..dffee90b177f 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,2159 +1,2184 @@
-/* $OpenBSD: sshconnect2.c,v 1.288 2018/10/11 03:48:04 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.303 2019/02/12 23:53:10 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
#include <vis.h>
#endif
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "sshbuf.h"
#include "packet.h"
#include "compat.h"
#include "cipher.h"
#include "sshkey.h"
#include "kex.h"
#include "myproposal.h"
#include "sshconnect.h"
#include "authfile.h"
#include "dh.h"
#include "authfd.h"
#include "log.h"
#include "misc.h"
#include "readconf.h"
#include "match.h"
#include "dispatch.h"
#include "canohost.h"
#include "msg.h"
#include "pathnames.h"
#include "uidswap.h"
#include "hostfile.h"
#include "ssherr.h"
#include "utf8.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
/* import */
extern char *client_version_string;
extern char *server_version_string;
extern Options options;
/*
* SSH2 key exchange
*/
u_char *session_id2 = NULL;
u_int session_id2_len = 0;
char *xxx_host;
struct sockaddr *xxx_hostaddr;
static int
verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
{
if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
fatal("Host key verification failed.");
return 0;
}
static char *
order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
{
char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
size_t maxlen;
struct hostkeys *hostkeys;
int ktype;
u_int i;
/* Find all hostkeys for this hostname */
get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL);
hostkeys = init_hostkeys();
for (i = 0; i < options.num_user_hostfiles; i++)
load_hostkeys(hostkeys, hostname, options.user_hostfiles[i]);
for (i = 0; i < options.num_system_hostfiles; i++)
load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
maxlen = strlen(avail) + 1;
first = xmalloc(maxlen);
last = xmalloc(maxlen);
*first = *last = '\0';
#define ALG_APPEND(to, from) \
do { \
if (*to != '\0') \
strlcat(to, ",", maxlen); \
strlcat(to, from, maxlen); \
} while (0)
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
fatal("%s: unknown alg %s", __func__, alg);
if (lookup_key_in_hostkeys_by_type(hostkeys,
sshkey_type_plain(ktype), NULL))
ALG_APPEND(first, alg);
else
ALG_APPEND(last, alg);
}
#undef ALG_APPEND
xasprintf(&ret, "%s%s%s", first,
(*first == '\0' || *last == '\0') ? "" : ",", last);
if (*first != '\0')
debug3("%s: prefer hostkeyalgs: %s", __func__, first);
free(first);
free(last);
free(hostname);
free(oavail);
free_hostkeys(hostkeys);
return ret;
}
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 *s, *all_key;
- struct kex *kex;
int r;
xxx_host = host;
xxx_hostaddr = hostaddr;
if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
fatal("%s: kex_names_cat", __func__);
myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
compat_cipher_proposal(options.ciphers);
myproposal[PROPOSAL_ENC_ALGS_STOC] =
compat_cipher_proposal(options.ciphers);
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
myproposal[PROPOSAL_COMP_ALGS_STOC] = options.compression ?
"zlib@openssh.com,zlib,none" : "none,zlib@openssh.com,zlib";
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
if (options.hostkeyalgorithms != NULL) {
all_key = sshkey_alg_list(0, 0, 1, ',');
if (kex_assemble_names(&options.hostkeyalgorithms,
KEX_DEFAULT_PK_ALG, all_key) != 0)
fatal("%s: kex_assemble_namelist", __func__);
free(all_key);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
compat_pkalg_proposal(options.hostkeyalgorithms);
} else {
/* Enforce default */
options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG);
/* Prefer algorithms that we already have keys for */
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
compat_pkalg_proposal(
order_hostkeyalgs(host, hostaddr, port));
}
if (options.rekey_limit || options.rekey_interval)
- packet_set_rekey_limits(options.rekey_limit,
+ ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
options.rekey_interval);
/* 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));
- kex = active_state->kex;
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
- kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
- kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client;
- kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client;
- kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client;
- kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
- kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
+ ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
+ ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
+ ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
# endif
#endif
- kex->kex[KEX_C25519_SHA256] = kexc25519_client;
- kex->client_version_string=client_version_string;
- kex->server_version_string=server_version_string;
- kex->verify_host_key=&verify_host_key_callback;
+ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
+ ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
+ ssh->kex->verify_host_key=&verify_host_key_callback;
- 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 */
myproposal[PROPOSAL_KEX_ALGS] =
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));
- session_id2 = kex->session_id;
- session_id2_len = kex->session_id_len;
+ session_id2 = ssh->kex->session_id;
+ session_id2_len = ssh->kex->session_id_len;
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_cstring(ssh, "markus")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
#endif
}
/*
* Authenticate user
*/
typedef struct cauthctxt Authctxt;
typedef struct cauthmethod Authmethod;
typedef struct identity Identity;
typedef struct idlist Idlist;
struct identity {
TAILQ_ENTRY(identity) next;
int agent_fd; /* >=0 if agent supports key */
struct sshkey *key; /* public/private key */
char *filename; /* comment for agent-only keys */
int tried;
int isprivate; /* key points to the private key */
int userprovided;
};
TAILQ_HEAD(idlist, identity);
struct cauthctxt {
const char *server_user;
const char *local_user;
const char *host;
const char *service;
struct cauthmethod *method;
sig_atomic_t success;
char *authlist;
- int attempt;
+#ifdef GSSAPI
+ /* gssapi */
+ gss_OID_set gss_supported_mechs;
+ u_int mech_tried;
+#endif
/* pubkey */
struct idlist keys;
int agent_fd;
/* hostbased */
Sensitive *sensitive;
char *oktypes, *ktypes;
const char *active_ktype;
/* kbd-interactive */
int info_req_seen;
+ int attempt_kbdint;
+ /* password */
+ int attempt_passwd;
/* generic */
void *methoddata;
};
struct cauthmethod {
char *name; /* string to compare against server's list */
- int (*userauth)(Authctxt *authctxt);
- void (*cleanup)(Authctxt *authctxt);
+ int (*userauth)(struct ssh *ssh);
+ void (*cleanup)(struct ssh *ssh);
int *enabled; /* flag in option struct that enables method */
int *batch_flag; /* flag in option struct that disables method */
};
-int input_userauth_service_accept(int, u_int32_t, struct ssh *);
-int input_userauth_ext_info(int, u_int32_t, struct ssh *);
-int input_userauth_success(int, u_int32_t, struct ssh *);
-int input_userauth_success_unexpected(int, u_int32_t, struct ssh *);
-int input_userauth_failure(int, u_int32_t, struct ssh *);
-int input_userauth_banner(int, u_int32_t, struct ssh *);
-int input_userauth_error(int, u_int32_t, struct ssh *);
-int input_userauth_info_req(int, u_int32_t, struct ssh *);
-int input_userauth_pk_ok(int, u_int32_t, struct ssh *);
-int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *);
-
-int userauth_none(Authctxt *);
-int userauth_pubkey(Authctxt *);
-int userauth_passwd(Authctxt *);
-int userauth_kbdint(Authctxt *);
-int userauth_hostbased(Authctxt *);
+static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
+static int input_userauth_ext_info(int, u_int32_t, struct ssh *);
+static int input_userauth_success(int, u_int32_t, struct ssh *);
+static int input_userauth_failure(int, u_int32_t, struct ssh *);
+static int input_userauth_banner(int, u_int32_t, struct ssh *);
+static int input_userauth_error(int, u_int32_t, struct ssh *);
+static int input_userauth_info_req(int, u_int32_t, struct ssh *);
+static int input_userauth_pk_ok(int, u_int32_t, struct ssh *);
+static int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *);
+
+static int userauth_none(struct ssh *);
+static int userauth_pubkey(struct ssh *);
+static int userauth_passwd(struct ssh *);
+static int userauth_kbdint(struct ssh *);
+static int userauth_hostbased(struct ssh *);
#ifdef GSSAPI
-int userauth_gssapi(Authctxt *authctxt);
-int input_gssapi_response(int type, u_int32_t, struct ssh *);
-int input_gssapi_token(int type, u_int32_t, struct ssh *);
-int input_gssapi_hash(int type, u_int32_t, struct ssh *);
-int input_gssapi_error(int, u_int32_t, struct ssh *);
-int input_gssapi_errtok(int, u_int32_t, struct ssh *);
+static int userauth_gssapi(struct ssh *);
+static void userauth_gssapi_cleanup(struct ssh *);
+static int input_gssapi_response(int type, u_int32_t, struct ssh *);
+static int input_gssapi_token(int type, u_int32_t, struct ssh *);
+static int input_gssapi_error(int, u_int32_t, struct ssh *);
+static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
#endif
-void userauth(Authctxt *, char *);
+void userauth(struct ssh *, char *);
-static int sign_and_send_pubkey(struct ssh *ssh, Authctxt *, Identity *);
+static void pubkey_cleanup(struct ssh *);
+static int sign_and_send_pubkey(struct ssh *ssh, Identity *);
static void pubkey_prepare(Authctxt *);
-static void pubkey_cleanup(Authctxt *);
static void pubkey_reset(Authctxt *);
static struct sshkey *load_identity_file(Identity *);
static Authmethod *authmethod_get(char *authlist);
static Authmethod *authmethod_lookup(const char *name);
static char *authmethods_get(void);
Authmethod authmethods[] = {
#ifdef GSSAPI
{"gssapi-with-mic",
userauth_gssapi,
- NULL,
+ userauth_gssapi_cleanup,
&options.gss_authentication,
NULL},
#endif
{"hostbased",
userauth_hostbased,
NULL,
&options.hostbased_authentication,
NULL},
{"publickey",
userauth_pubkey,
NULL,
&options.pubkey_authentication,
NULL},
{"keyboard-interactive",
userauth_kbdint,
NULL,
&options.kbd_interactive_authentication,
&options.batch_mode},
{"password",
userauth_passwd,
NULL,
&options.password_authentication,
&options.batch_mode},
{"none",
userauth_none,
NULL,
NULL,
NULL},
{NULL, NULL, NULL, NULL, NULL}
};
void
-ssh_userauth2(const char *local_user, const char *server_user, char *host,
- Sensitive *sensitive)
+ssh_userauth2(struct ssh *ssh, const char *local_user,
+ const char *server_user, char *host, Sensitive *sensitive)
{
- struct ssh *ssh = active_state;
Authctxt authctxt;
int r;
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
if (options.preferred_authentications == NULL)
options.preferred_authentications = authmethods_get();
/* setup authentication context */
memset(&authctxt, 0, sizeof(authctxt));
- pubkey_prepare(&authctxt);
authctxt.server_user = server_user;
authctxt.local_user = local_user;
authctxt.host = host;
authctxt.service = "ssh-connection"; /* service name */
authctxt.success = 0;
authctxt.method = authmethod_lookup("none");
authctxt.authlist = NULL;
authctxt.methoddata = NULL;
authctxt.sensitive = sensitive;
authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL;
authctxt.info_req_seen = 0;
+ authctxt.attempt_kbdint = 0;
+ authctxt.attempt_passwd = 0;
+#if GSSAPI
+ authctxt.gss_supported_mechs = NULL;
+ authctxt.mech_tried = 0;
+#endif
authctxt.agent_fd = -1;
- if (authctxt.method == NULL)
- fatal("ssh_userauth2: internal error: cannot send userauth none request");
+ pubkey_prepare(&authctxt);
+ if (authctxt.method == NULL) {
+ fatal("%s: internal error: cannot send userauth none request",
+ __func__);
+ }
if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
ssh->authctxt = &authctxt;
ssh_dispatch_init(ssh, &input_userauth_error);
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */
+ pubkey_cleanup(ssh);
ssh->authctxt = NULL;
- pubkey_cleanup(&authctxt);
ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL);
if (!authctxt.success)
fatal("Authentication failed.");
debug("Authentication succeeded (%s).", authctxt.method->name);
}
/* ARGSUSED */
-int
+static int
input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
{
- Authctxt *authctxt = ssh->authctxt;
int r;
if (ssh_packet_remaining(ssh) > 0) {
char *reply;
if ((r = sshpkt_get_cstring(ssh, &reply, NULL)) != 0)
goto out;
debug2("service_accept: %s", reply);
free(reply);
} else {
debug2("buggy server: service_accept w/o service");
}
if ((r = sshpkt_get_end(ssh)) != 0)
goto out;
debug("SSH2_MSG_SERVICE_ACCEPT received");
/* initial userauth request */
- userauth_none(authctxt);
+ userauth_none(ssh);
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_error);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
r = 0;
out:
return r;
}
/* ARGSUSED */
-int
+static int
input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh)
{
return kex_input_ext_info(type, seqnr, ssh);
}
void
-userauth(Authctxt *authctxt, char *authlist)
+userauth(struct ssh *ssh, char *authlist)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
- authctxt->method->cleanup(authctxt);
+ authctxt->method->cleanup(ssh);
free(authctxt->methoddata);
authctxt->methoddata = NULL;
if (authlist == NULL) {
authlist = authctxt->authlist;
} else {
free(authctxt->authlist);
authctxt->authlist = authlist;
}
for (;;) {
Authmethod *method = authmethod_get(authlist);
if (method == NULL)
fatal("%s@%s: Permission denied (%s).",
authctxt->server_user, authctxt->host, authlist);
authctxt->method = method;
/* reset the per method handler */
ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_PER_METHOD_MIN,
SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL);
/* and try new method */
- if (method->userauth(authctxt) != 0) {
+ if (method->userauth(ssh) != 0) {
debug2("we sent a %s packet, wait for reply", method->name);
break;
} else {
debug2("we did not send a packet, disable method");
method->enabled = NULL;
}
}
}
/* ARGSUSED */
-int
+static int
input_userauth_error(int type, u_int32_t seq, struct ssh *ssh)
{
- fatal("input_userauth_error: bad message during authentication: "
- "type %d", type);
+ fatal("%s: bad message during authentication: type %d", __func__, type);
return 0;
}
/* ARGSUSED */
-int
+static int
input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh)
{
- char *msg, *lang;
- u_int len;
+ char *msg = NULL;
+ size_t len;
+ int r;
debug3("%s", __func__);
- msg = packet_get_string(&len);
- lang = packet_get_string(NULL);
+ if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 ||
+ (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0)
+ goto out;
if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO)
fmprintf(stderr, "%s", msg);
+ r = 0;
+ out:
free(msg);
- free(lang);
- return 0;
+ return r;
}
/* ARGSUSED */
-int
+static int
input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
if (authctxt == NULL)
- fatal("input_userauth_success: no authentication context");
+ fatal("%s: no authentication context", __func__);
free(authctxt->authlist);
authctxt->authlist = NULL;
if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
- authctxt->method->cleanup(authctxt);
+ authctxt->method->cleanup(ssh);
free(authctxt->methoddata);
authctxt->methoddata = NULL;
authctxt->success = 1; /* break out */
return 0;
}
-int
+#if 0
+static int
input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
if (authctxt == NULL)
fatal("%s: no authentication context", __func__);
fatal("Unexpected authentication success during %s.",
authctxt->method->name);
return 0;
}
+#endif
/* ARGSUSED */
-int
+static int
input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
char *authlist = NULL;
u_char partial;
int r;
if (authctxt == NULL)
fatal("input_userauth_failure: no authentication context");
if ((r = sshpkt_get_cstring(ssh, &authlist, NULL)) != 0 ||
(r = sshpkt_get_u8(ssh, &partial)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
if (partial != 0) {
verbose("Authenticated with partial success.");
/* reset state */
pubkey_reset(authctxt);
}
debug("Authentications that can continue: %s", authlist);
- userauth(authctxt, authlist);
+ userauth(ssh, authlist);
authlist = NULL;
out:
free(authlist);
return 0;
}
/*
* Format an identity for logging including filename, key type, fingerprint
* and location (agent, etc.). Caller must free.
*/
static char *
format_identity(Identity *id)
{
char *fp = NULL, *ret = NULL;
if (id->key != NULL) {
fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
SSH_FP_DEFAULT);
}
xasprintf(&ret, "%s %s%s%s%s%s%s",
id->filename,
id->key ? sshkey_type(id->key) : "", id->key ? " " : "",
fp ? fp : "",
id->userprovided ? " explicit" : "",
(id->key && (id->key->flags & SSHKEY_FLAG_EXT)) ? " token" : "",
id->agent_fd != -1 ? " agent" : "");
free(fp);
return ret;
}
/* ARGSUSED */
-int
+static int
input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
struct sshkey *key = NULL;
Identity *id = NULL;
int pktype, found = 0, sent = 0;
size_t blen;
char *pkalg = NULL, *fp = NULL, *ident = NULL;
u_char *pkblob = NULL;
int r;
if (authctxt == NULL)
fatal("input_userauth_pk_ok: no authentication context");
if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto done;
if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) {
debug("%s: server sent unknown pkalg %s", __func__, pkalg);
goto done;
}
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
debug("no key from blob. pkalg %s: %s", pkalg, ssh_err(r));
goto done;
}
if (key->type != pktype) {
error("input_userauth_pk_ok: type mismatch "
"for decoded key (received %d, expected %d)",
key->type, pktype);
goto done;
}
/*
* search keys in the reverse order, because last candidate has been
* moved to the end of the queue. this also avoids confusion by
* duplicate keys
*/
TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) {
if (sshkey_equal(key, id->key)) {
found = 1;
break;
}
}
if (!found || id == NULL) {
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
error("%s: server replied with unknown key: %s %s", __func__,
sshkey_type(key), fp == NULL ? "<ERROR>" : fp);
goto done;
}
ident = format_identity(id);
debug("Server accepts key: %s", ident);
- sent = sign_and_send_pubkey(ssh, authctxt, id);
+ sent = sign_and_send_pubkey(ssh, id);
r = 0;
done:
sshkey_free(key);
free(ident);
free(fp);
free(pkalg);
free(pkblob);
/* try another method if we did not send a packet */
if (r == 0 && sent == 0)
- userauth(authctxt, NULL);
+ userauth(ssh, NULL);
return r;
}
#ifdef GSSAPI
-int
-userauth_gssapi(Authctxt *authctxt)
+static int
+userauth_gssapi(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
Gssctxt *gssctxt = NULL;
- static gss_OID_set gss_supported = NULL;
- static u_int mech = 0;
OM_uint32 min;
int r, ok = 0;
+ gss_OID mech = NULL;
/* Try one GSSAPI method at a time, rather than sending them all at
* once. */
- if (gss_supported == NULL)
- gss_indicate_mechs(&min, &gss_supported);
+ if (authctxt->gss_supported_mechs == NULL)
+ gss_indicate_mechs(&min, &authctxt->gss_supported_mechs);
- /* Check to see if the mechanism is usable before we offer it */
- while (mech < gss_supported->count && !ok) {
+ /* Check to see whether the mechanism is usable before we offer it */
+ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count &&
+ !ok) {
+ mech = &authctxt->gss_supported_mechs->
+ elements[authctxt->mech_tried];
/* My DER encoding requires length<128 */
- if (gss_supported->elements[mech].length < 128 &&
- ssh_gssapi_check_mechanism(&gssctxt,
- &gss_supported->elements[mech], authctxt->host)) {
+ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt,
+ mech, authctxt->host)) {
ok = 1; /* Mechanism works */
} else {
- mech++;
+ authctxt->mech_tried++;
}
}
- if (!ok)
+ if (!ok || mech == NULL)
return 0;
authctxt->methoddata=(void *)gssctxt;
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_put_u32(ssh, 1)) != 0 ||
- (r = sshpkt_put_u32(ssh,
- (gss_supported->elements[mech].length) + 2)) != 0 ||
+ (r = sshpkt_put_u32(ssh, (mech->length) + 2)) != 0 ||
(r = sshpkt_put_u8(ssh, SSH_GSS_OIDTYPE)) != 0 ||
- (r = sshpkt_put_u8(ssh,
- gss_supported->elements[mech].length)) != 0 ||
- (r = sshpkt_put(ssh,
- gss_supported->elements[mech].elements,
- gss_supported->elements[mech].length)) != 0 ||
+ (r = sshpkt_put_u8(ssh, mech->length)) != 0 ||
+ (r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok);
- mech++; /* Move along to next candidate */
+ authctxt->mech_tried++; /* Move along to next candidate */
return 1;
}
+static void
+userauth_gssapi_cleanup(struct ssh *ssh)
+{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata;
+
+ ssh_gssapi_delete_ctx(&gssctxt);
+ authctxt->methoddata = NULL;
+
+ free(authctxt->gss_supported_mechs);
+ authctxt->gss_supported_mechs = NULL;
+}
+
static OM_uint32
process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok)
{
Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt = authctxt->methoddata;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
gss_buffer_desc gssbuf;
OM_uint32 status, ms, flags;
int r;
status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
recv_tok, &send_tok, &flags);
if (send_tok.length > 0) {
u_char type = GSS_ERROR(status) ?
SSH2_MSG_USERAUTH_GSSAPI_ERRTOK :
SSH2_MSG_USERAUTH_GSSAPI_TOKEN;
if ((r = sshpkt_start(ssh, type)) != 0 ||
(r = sshpkt_put_string(ssh, send_tok.value,
send_tok.length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
gss_release_buffer(&ms, &send_tok);
}
if (status == GSS_S_COMPLETE) {
/* send either complete or MIC, depending on mechanism */
if (!(flags & GSS_C_INTEG_FLAG)) {
if ((r = sshpkt_start(ssh,
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
} else {
struct sshbuf *b;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
ssh_gssapi_buildmic(b, authctxt->server_user,
authctxt->service, "gssapi-with-mic");
if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
fatal("%s: sshbuf_mutable_ptr failed", __func__);
gssbuf.length = sshbuf_len(b);
status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
if (!GSS_ERROR(status)) {
if ((r = sshpkt_start(ssh,
SSH2_MSG_USERAUTH_GSSAPI_MIC)) != 0 ||
(r = sshpkt_put_string(ssh, mic.value,
mic.length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
}
sshbuf_free(b);
gss_release_buffer(&ms, &mic);
}
}
return status;
}
/* ARGSUSED */
-int
+static int
input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
size_t oidlen;
u_char *oidv = NULL;
int r;
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
gssctxt = authctxt->methoddata;
/* Setup our OID */
if ((r = sshpkt_get_string(ssh, &oidv, &oidlen)) != 0)
goto done;
if (oidlen <= 2 ||
oidv[0] != SSH_GSS_OIDTYPE ||
oidv[1] != oidlen - 2) {
debug("Badly encoded mechanism OID received");
- userauth(authctxt, NULL);
+ userauth(ssh, NULL);
goto ok;
}
if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2))
fatal("Server returned different OID than expected");
if ((r = sshpkt_get_end(ssh)) != 0)
goto done;
if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) {
/* Start again with next method on list */
debug("Trying to start again");
- userauth(authctxt, NULL);
+ userauth(ssh, NULL);
goto ok;
}
ok:
r = 0;
done:
free(oidv);
return r;
}
/* ARGSUSED */
-int
+static int
input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
gss_buffer_desc recv_tok;
u_char *p = NULL;
size_t len;
OM_uint32 status;
int r;
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
goto out;
recv_tok.value = p;
recv_tok.length = len;
status = process_gssapi_token(ssh, &recv_tok);
/* Start again with the next method in the list */
if (GSS_ERROR(status)) {
- userauth(authctxt, NULL);
+ userauth(ssh, NULL);
/* ok */
}
r = 0;
out:
free(p);
return r;
}
/* ARGSUSED */
-int
+static int
input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
Gssctxt *gssctxt;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc recv_tok;
OM_uint32 ms;
u_char *p = NULL;
size_t len;
int r;
if (authctxt == NULL)
fatal("input_gssapi_response: no authentication context");
gssctxt = authctxt->methoddata;
if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
free(p);
return r;
}
/* Stick it into GSSAPI and see what it says */
recv_tok.value = p;
recv_tok.length = len;
(void)ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
&recv_tok, &send_tok, NULL);
free(p);
gss_release_buffer(&ms, &send_tok);
/* Server will be returning a failed packet after this one */
return 0;
}
/* ARGSUSED */
-int
+static int
input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
{
char *msg = NULL;
char *lang = NULL;
int r;
if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* maj */
(r = sshpkt_get_u32(ssh, NULL)) != 0 || /* min */
(r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0)
goto out;
r = sshpkt_get_end(ssh);
debug("Server GSSAPI Error:\n%s", msg);
out:
free(msg);
free(lang);
return r;
}
#endif /* GSSAPI */
-int
-userauth_none(Authctxt *authctxt)
+static int
+userauth_none(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
int r;
/* initial userauth request */
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
return 1;
}
-int
-userauth_passwd(Authctxt *authctxt)
+static int
+userauth_passwd(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
- static int attempt = 0;
- char prompt[256];
- char *password;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
+ char *password, *prompt = NULL;
const char *host = options.host_key_alias ? options.host_key_alias :
authctxt->host;
int r;
- if (attempt++ >= options.number_of_password_prompts)
+ if (authctxt->attempt_passwd++ >= options.number_of_password_prompts)
return 0;
- if (attempt != 1)
+ if (authctxt->attempt_passwd != 1)
error("Permission denied, please try again.");
- snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
- authctxt->server_user, host);
+ xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host);
password = read_passphrase(prompt, 0);
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 ||
(r = sshpkt_put_cstring(ssh, password)) != 0 ||
(r = sshpkt_add_padding(ssh, 64)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
- if (password)
+ free(prompt);
+ if (password != NULL)
freezero(password, strlen(password));
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
&input_userauth_passwd_changereq);
return 1;
}
/*
* parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST
*/
/* ARGSUSED */
-int
+static int
input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
char *info = NULL, *lang = NULL, *password = NULL, *retype = NULL;
char prompt[256];
const char *host;
int r;
debug2("input_userauth_passwd_changereq");
if (authctxt == NULL)
fatal("input_userauth_passwd_changereq: "
"no authentication context");
host = options.host_key_alias ? options.host_key_alias : authctxt->host;
if ((r = sshpkt_get_cstring(ssh, &info, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0)
goto out;
if (strlen(info) > 0)
logit("%s", info);
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_put_u8(ssh, 1)) != 0) /* additional info */
goto out;
snprintf(prompt, sizeof(prompt),
"Enter %.30s@%.128s's old password: ",
authctxt->server_user, host);
password = read_passphrase(prompt, 0);
if ((r = sshpkt_put_cstring(ssh, password)) != 0)
goto out;
freezero(password, strlen(password));
password = NULL;
while (password == NULL) {
snprintf(prompt, sizeof(prompt),
"Enter %.30s@%.128s's new password: ",
authctxt->server_user, host);
password = read_passphrase(prompt, RP_ALLOW_EOF);
if (password == NULL) {
/* bail out */
r = 0;
goto out;
}
snprintf(prompt, sizeof(prompt),
"Retype %.30s@%.128s's new password: ",
authctxt->server_user, host);
retype = read_passphrase(prompt, 0);
if (strcmp(password, retype) != 0) {
freezero(password, strlen(password));
logit("Mismatch; try again, EOF to quit.");
password = NULL;
}
freezero(retype, strlen(retype));
}
if ((r = sshpkt_put_cstring(ssh, password)) != 0 ||
(r = sshpkt_add_padding(ssh, 64)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
goto out;
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ,
&input_userauth_passwd_changereq);
r = 0;
out:
if (password)
freezero(password, strlen(password));
free(info);
free(lang);
return r;
}
/*
* Select an algorithm for publickey signatures.
* Returns algorithm (caller must free) or NULL if no mutual algorithm found.
*
* Call with ssh==NULL to ignore server-sig-algs extension list and
* only attempt with the key's base signature type.
*/
static char *
key_sig_algorithm(struct ssh *ssh, const struct sshkey *key)
{
char *allowed, *oallowed, *cp, *tmp, *alg = NULL;
/*
* The signature algorithm will only differ from the key algorithm
* for RSA keys/certs and when the server advertises support for
* newer (SHA2) algorithms.
*/
if (ssh == NULL || ssh->kex->server_sig_algs == NULL ||
(key->type != KEY_RSA && key->type != KEY_RSA_CERT) ||
(key->type == KEY_RSA_CERT && (datafellows & SSH_BUG_SIGTYPE))) {
/* Filter base key signature alg against our configuration */
return match_list(sshkey_ssh_name(key),
options.pubkey_key_types, NULL);
}
/*
* For RSA keys/certs, since these might have a different sig type:
* find the first entry in PubkeyAcceptedKeyTypes of the right type
* that also appears in the supported signature algorithms list from
* the server.
*/
oallowed = allowed = xstrdup(options.pubkey_key_types);
while ((cp = strsep(&allowed, ",")) != NULL) {
if (sshkey_type_from_name(cp) != key->type)
continue;
tmp = match_list(sshkey_sigalg_by_name(cp), ssh->kex->server_sig_algs, NULL);
if (tmp != NULL)
alg = xstrdup(cp);
free(tmp);
if (alg != NULL)
break;
}
free(oallowed);
return alg;
}
static int
identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat, const char *alg)
{
struct sshkey *prv;
int r;
/* The agent supports this key. */
if (id->key != NULL && id->agent_fd != -1) {
return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp,
data, datalen, alg, compat);
}
/*
* We have already loaded the private key or the private key is
* stored in external hardware.
*/
if (id->key != NULL &&
(id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) {
if ((r = sshkey_sign(id->key, sigp, lenp, data, datalen,
alg, compat)) != 0)
return r;
/*
* PKCS#11 tokens may not support all signature algorithms,
* so check what we get back.
*/
if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0)
return r;
return 0;
}
/* Load the private key from the file. */
if ((prv = load_identity_file(id)) == NULL)
return SSH_ERR_KEY_NOT_FOUND;
if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
error("%s: private key %s contents do not match public",
__func__, id->filename);
return SSH_ERR_KEY_NOT_FOUND;
}
r = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat);
sshkey_free(prv);
return r;
}
static int
id_filename_matches(Identity *id, Identity *private_id)
{
const char *suffixes[] = { ".pub", "-cert.pub", NULL };
size_t len = strlen(id->filename), plen = strlen(private_id->filename);
size_t i, slen;
if (strcmp(id->filename, private_id->filename) == 0)
return 1;
for (i = 0; suffixes[i]; i++) {
slen = strlen(suffixes[i]);
if (len > slen && plen == len - slen &&
strcmp(id->filename + (len - slen), suffixes[i]) == 0 &&
memcmp(id->filename, private_id->filename, plen) == 0)
return 1;
}
return 0;
}
static int
-sign_and_send_pubkey(struct ssh *ssh, Authctxt *authctxt, Identity *id)
+sign_and_send_pubkey(struct ssh *ssh, Identity *id)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
struct sshbuf *b = NULL;
Identity *private_id, *sign_id = NULL;
u_char *signature = NULL;
size_t slen = 0, skip = 0;
int r, fallback_sigtype, sent = 0;
char *alg = NULL, *fp = NULL;
const char *loc = "";
if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
return 0;
debug3("%s: %s %s", __func__, sshkey_type(id->key), fp);
/*
* If the key is an certificate, try to find a matching private key
* and use it to complete the signature.
* If no such private key exists, fall back to trying the certificate
* key itself in case it has a private half already loaded.
* This will try to set sign_id to the private key that will perform
* the signature.
*/
if (sshkey_is_cert(id->key)) {
TAILQ_FOREACH(private_id, &authctxt->keys, next) {
if (sshkey_equal_public(id->key, private_id->key) &&
id->key->type != private_id->key->type) {
sign_id = private_id;
break;
}
}
/*
* Exact key matches are preferred, but also allow
* filename matches for non-PKCS#11/agent keys that
* didn't load public keys. This supports the case
* of keeping just a private key file and public
* certificate on disk.
*/
if (sign_id == NULL &&
!id->isprivate && id->agent_fd == -1 &&
(id->key->flags & SSHKEY_FLAG_EXT) == 0) {
TAILQ_FOREACH(private_id, &authctxt->keys, next) {
if (private_id->key == NULL &&
id_filename_matches(id, private_id)) {
sign_id = private_id;
break;
}
}
}
if (sign_id != NULL) {
debug2("%s: using private key \"%s\"%s for "
"certificate", __func__, id->filename,
id->agent_fd != -1 ? " from agent" : "");
} else {
debug("%s: no separate private key for certificate "
"\"%s\"", __func__, id->filename);
}
}
/*
* If the above didn't select another identity to do the signing
* then default to the one we started with.
*/
if (sign_id == NULL)
sign_id = id;
/* assemble and sign data */
for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) {
free(alg);
slen = 0;
signature = NULL;
if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh,
id->key)) == NULL) {
error("%s: no mutual signature supported", __func__);
goto out;
}
debug3("%s: signing using %s", __func__, alg);
sshbuf_free(b);
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (datafellows & SSH_OLD_SESSIONID) {
if ((r = sshbuf_put(b, session_id2,
session_id2_len)) != 0) {
fatal("%s: sshbuf_put: %s",
__func__, ssh_err(r));
}
} else {
if ((r = sshbuf_put_string(b, session_id2,
session_id2_len)) != 0) {
fatal("%s: sshbuf_put_string: %s",
__func__, ssh_err(r));
}
}
skip = sshbuf_len(b);
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
(r = sshbuf_put_u8(b, 1)) != 0 ||
(r = sshbuf_put_cstring(b, alg)) != 0 ||
(r = sshkey_puts(id->key, b)) != 0) {
fatal("%s: assemble signed data: %s",
__func__, ssh_err(r));
}
/* generate signature */
r = identity_sign(sign_id, &signature, &slen,
sshbuf_ptr(b), sshbuf_len(b), datafellows, alg);
if (r == 0)
break;
else if (r == SSH_ERR_KEY_NOT_FOUND)
goto out; /* soft failure */
else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED &&
!fallback_sigtype) {
if (sign_id->agent_fd != -1)
loc = "agent ";
else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0)
loc = "token ";
logit("%skey %s %s returned incorrect signature type",
loc, sshkey_type(id->key), fp);
continue;
}
error("%s: signing failed: %s", __func__, ssh_err(r));
goto out;
}
if (slen == 0 || signature == NULL) /* shouldn't happen */
fatal("%s: no signature", __func__);
/* append signature */
if ((r = sshbuf_put_string(b, signature, slen)) != 0)
fatal("%s: append signature: %s", __func__, ssh_err(r));
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
/* skip session id and packet type */
if ((r = sshbuf_consume(b, skip + 1)) != 0)
fatal("%s: consume: %s", __func__, ssh_err(r));
/* put remaining data from buffer into packet */
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_putb(ssh, b)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: enqueue request: %s", __func__, ssh_err(r));
/* success */
sent = 1;
out:
free(fp);
free(alg);
sshbuf_free(b);
freezero(signature, slen);
return sent;
}
static int
-send_pubkey_test(struct ssh *ssh, Authctxt *authctxt, Identity *id)
+send_pubkey_test(struct ssh *ssh, Identity *id)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
u_char *blob = NULL;
char *alg = NULL;
size_t bloblen;
u_int have_sig = 0;
int sent = 0, r;
if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) {
debug("%s: no mutual signature algorithm", __func__);
goto out;
}
if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) {
/* we cannot handle this key */
debug3("%s: cannot handle key", __func__);
goto out;
}
/* register callback for USERAUTH_PK_OK message */
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_put_u8(ssh, have_sig)) != 0 ||
(r = sshpkt_put_cstring(ssh, alg)) != 0 ||
(r = sshpkt_put_string(ssh, blob, bloblen)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
sent = 1;
out:
free(alg);
free(blob);
return sent;
}
static struct sshkey *
load_identity_file(Identity *id)
{
struct sshkey *private = NULL;
char prompt[300], *passphrase, *comment;
int r, perm_ok = 0, quit = 0, i;
struct stat st;
if (stat(id->filename, &st) < 0) {
(id->userprovided ? logit : debug3)("no such identity: %s: %s",
id->filename, strerror(errno));
return NULL;
}
snprintf(prompt, sizeof prompt,
"Enter passphrase for key '%.100s': ", id->filename);
for (i = 0; i <= options.number_of_password_prompts; i++) {
if (i == 0)
passphrase = "";
else {
passphrase = read_passphrase(prompt, 0);
if (*passphrase == '\0') {
debug2("no passphrase given, try next key");
free(passphrase);
break;
}
}
switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename,
passphrase, &private, &comment, &perm_ok))) {
case 0:
break;
case SSH_ERR_KEY_WRONG_PASSPHRASE:
if (options.batch_mode) {
quit = 1;
break;
}
if (i != 0)
debug2("bad passphrase given, try again...");
break;
case SSH_ERR_SYSTEM_ERROR:
if (errno == ENOENT) {
debug2("Load key \"%s\": %s",
id->filename, ssh_err(r));
quit = 1;
break;
}
/* FALLTHROUGH */
default:
error("Load key \"%s\": %s", id->filename, ssh_err(r));
quit = 1;
break;
}
if (!quit && private != NULL && id->agent_fd == -1 &&
!(id->key && id->isprivate))
maybe_add_key_to_agent(id->filename, private, comment,
passphrase);
if (i > 0)
freezero(passphrase, strlen(passphrase));
free(comment);
if (private != NULL || quit)
break;
}
return private;
}
static int
key_type_allowed_by_config(struct sshkey *key)
{
if (match_pattern_list(sshkey_ssh_name(key),
options.pubkey_key_types, 0) == 1)
return 1;
/* RSA keys/certs might be allowed by alternate signature types */
switch (key->type) {
case KEY_RSA:
if (match_pattern_list("rsa-sha2-512",
options.pubkey_key_types, 0) == 1)
return 1;
if (match_pattern_list("rsa-sha2-256",
options.pubkey_key_types, 0) == 1)
return 1;
break;
case KEY_RSA_CERT:
if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
options.pubkey_key_types, 0) == 1)
return 1;
if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
options.pubkey_key_types, 0) == 1)
return 1;
break;
}
return 0;
}
/*
* try keys in the following order:
* 1. certificates listed in the config file
* 2. other input certificates
* 3. agent keys that are found in the config file
* 4. other agent keys
* 5. keys that are only listed in the config file
*/
static void
pubkey_prepare(Authctxt *authctxt)
{
struct identity *id, *id2, *tmp;
struct idlist agent, files, *preferred;
struct sshkey *key;
int agent_fd = -1, i, r, found;
size_t j;
struct ssh_identitylist *idlist;
char *ident;
TAILQ_INIT(&agent); /* keys from the agent */
TAILQ_INIT(&files); /* keys from the config file */
preferred = &authctxt->keys;
TAILQ_INIT(preferred); /* preferred order of keys */
/* list of keys stored in the filesystem and PKCS#11 */
for (i = 0; i < options.num_identity_files; i++) {
key = options.identity_keys[i];
if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER)
continue;
options.identity_keys[i] = NULL;
id = xcalloc(1, sizeof(*id));
id->agent_fd = -1;
id->key = key;
id->filename = xstrdup(options.identity_files[i]);
id->userprovided = options.identity_file_userprovided[i];
TAILQ_INSERT_TAIL(&files, id, next);
}
/* list of certificates specified by user */
for (i = 0; i < options.num_certificate_files; i++) {
key = options.certificates[i];
if (!sshkey_is_cert(key) || key->cert == NULL ||
key->cert->type != SSH2_CERT_TYPE_USER)
continue;
id = xcalloc(1, sizeof(*id));
id->agent_fd = -1;
id->key = key;
id->filename = xstrdup(options.certificate_files[i]);
id->userprovided = options.certificate_file_userprovided[i];
TAILQ_INSERT_TAIL(preferred, id, next);
}
/* list of keys supported by the agent */
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
} else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
debug("%s: ssh_fetch_identitylist: %s",
__func__, ssh_err(r));
close(agent_fd);
} else {
for (j = 0; j < idlist->nkeys; j++) {
found = 0;
TAILQ_FOREACH(id, &files, next) {
/*
* agent keys from the config file are
* preferred
*/
if (sshkey_equal(idlist->keys[j], id->key)) {
TAILQ_REMOVE(&files, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
id->agent_fd = agent_fd;
found = 1;
break;
}
}
if (!found && !options.identities_only) {
id = xcalloc(1, sizeof(*id));
/* XXX "steals" key/comment from idlist */
id->key = idlist->keys[j];
id->filename = idlist->comments[j];
idlist->keys[j] = NULL;
idlist->comments[j] = NULL;
id->agent_fd = agent_fd;
TAILQ_INSERT_TAIL(&agent, id, next);
}
}
ssh_free_identitylist(idlist);
/* append remaining agent keys */
for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
TAILQ_REMOVE(&agent, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
}
authctxt->agent_fd = agent_fd;
}
/* Prefer PKCS11 keys that are explicitly listed */
TAILQ_FOREACH_SAFE(id, &files, next, tmp) {
if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0)
continue;
found = 0;
TAILQ_FOREACH(id2, &files, next) {
if (id2->key == NULL ||
(id2->key->flags & SSHKEY_FLAG_EXT) == 0)
continue;
if (sshkey_equal(id->key, id2->key)) {
TAILQ_REMOVE(&files, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
found = 1;
break;
}
}
/* If IdentitiesOnly set and key not found then don't use it */
if (!found && options.identities_only) {
TAILQ_REMOVE(&files, id, next);
freezero(id, sizeof(*id));
}
}
/* append remaining keys from the config file */
for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
TAILQ_REMOVE(&files, id, next);
TAILQ_INSERT_TAIL(preferred, id, next);
}
/* finally, filter by PubkeyAcceptedKeyTypes */
TAILQ_FOREACH_SAFE(id, preferred, next, id2) {
if (id->key != NULL && !key_type_allowed_by_config(id->key)) {
debug("Skipping %s key %s - "
"not in PubkeyAcceptedKeyTypes",
sshkey_ssh_name(id->key), id->filename);
TAILQ_REMOVE(preferred, id, next);
sshkey_free(id->key);
free(id->filename);
memset(id, 0, sizeof(*id));
continue;
}
}
/* List the keys we plan on using */
TAILQ_FOREACH_SAFE(id, preferred, next, id2) {
ident = format_identity(id);
debug("Will attempt key: %s", ident);
free(ident);
}
debug2("%s: done", __func__);
}
static void
-pubkey_cleanup(Authctxt *authctxt)
+pubkey_cleanup(struct ssh *ssh)
{
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
Identity *id;
- if (authctxt->agent_fd != -1)
+ if (authctxt->agent_fd != -1) {
ssh_close_authentication_socket(authctxt->agent_fd);
+ authctxt->agent_fd = -1;
+ }
for (id = TAILQ_FIRST(&authctxt->keys); id;
id = TAILQ_FIRST(&authctxt->keys)) {
TAILQ_REMOVE(&authctxt->keys, id, next);
sshkey_free(id->key);
free(id->filename);
free(id);
}
}
static void
pubkey_reset(Authctxt *authctxt)
{
Identity *id;
TAILQ_FOREACH(id, &authctxt->keys, next)
id->tried = 0;
}
static int
try_identity(Identity *id)
{
if (!id->key)
return (0);
if (sshkey_type_plain(id->key->type) == KEY_RSA &&
(datafellows & SSH_BUG_RSASIGMD5) != 0) {
debug("Skipped %s key %s for RSA/MD5 server",
sshkey_type(id->key), id->filename);
return (0);
}
return 1;
}
-int
-userauth_pubkey(Authctxt *authctxt)
+static int
+userauth_pubkey(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
Identity *id;
int sent = 0;
char *ident;
while ((id = TAILQ_FIRST(&authctxt->keys))) {
if (id->tried++)
return (0);
/* move key to the end of the queue */
TAILQ_REMOVE(&authctxt->keys, id, next);
TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
/*
* send a test message if we have the public key. for
* encrypted keys we cannot do this and have to load the
* private key instead
*/
if (id->key != NULL) {
if (try_identity(id)) {
ident = format_identity(id);
debug("Offering public key: %s", ident);
free(ident);
- sent = send_pubkey_test(ssh, authctxt, id);
+ sent = send_pubkey_test(ssh, id);
}
} else {
debug("Trying private key: %s", id->filename);
id->key = load_identity_file(id);
if (id->key != NULL) {
if (try_identity(id)) {
id->isprivate = 1;
- sent = sign_and_send_pubkey(ssh,
- authctxt, id);
+ sent = sign_and_send_pubkey(ssh, id);
}
sshkey_free(id->key);
id->key = NULL;
id->isprivate = 0;
}
}
if (sent)
return (sent);
}
return (0);
}
/*
* Send userauth request message specifying keyboard-interactive method.
*/
-int
-userauth_kbdint(Authctxt *authctxt)
+static int
+userauth_kbdint(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
- static int attempt = 0;
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
int r;
- if (attempt++ >= options.number_of_password_prompts)
+ if (authctxt->attempt_kbdint++ >= options.number_of_password_prompts)
return 0;
/* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
- if (attempt > 1 && !authctxt->info_req_seen) {
+ if (authctxt->attempt_kbdint > 1 && !authctxt->info_req_seen) {
debug3("userauth_kbdint: disable: no info_req_seen");
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
return 0;
}
debug2("userauth_kbdint");
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 || /* lang */
(r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ?
options.kbd_interactive_devices : "")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
return 1;
}
/*
* parse INFO_REQUEST, prompt user and send INFO_RESPONSE
*/
-int
+static int
input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL;
char *response = NULL;
u_char echo = 0;
u_int num_prompts, i;
int r;
debug2("input_userauth_info_req");
if (authctxt == NULL)
fatal("input_userauth_info_req: no authentication context");
authctxt->info_req_seen = 1;
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &inst, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0)
goto out;
if (strlen(name) > 0)
logit("%s", name);
if (strlen(inst) > 0)
logit("%s", inst);
if ((r = sshpkt_get_u32(ssh, &num_prompts)) != 0)
goto out;
/*
* Begin to build info response packet based on prompts requested.
* We commit to providing the correct number of responses, so if
* further on we run into a problem that prevents this, we have to
* be sure and clean this up and send a correct error response.
*/
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE)) != 0 ||
(r = sshpkt_put_u32(ssh, num_prompts)) != 0)
goto out;
debug2("input_userauth_info_req: num_prompts %d", num_prompts);
for (i = 0; i < num_prompts; i++) {
if ((r = sshpkt_get_cstring(ssh, &prompt, NULL)) != 0 ||
(r = sshpkt_get_u8(ssh, &echo)) != 0)
goto out;
response = read_passphrase(prompt, echo ? RP_ECHO : 0);
if ((r = sshpkt_put_cstring(ssh, response)) != 0)
goto out;
freezero(response, strlen(response));
free(prompt);
response = prompt = NULL;
}
/* done with parsing incoming message. */
if ((r = sshpkt_get_end(ssh)) != 0 ||
(r = sshpkt_add_padding(ssh, 64)) != 0)
goto out;
r = sshpkt_send(ssh);
out:
if (response)
freezero(response, strlen(response));
free(prompt);
free(name);
free(inst);
free(lang);
return r;
}
static int
-ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp,
+ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen)
{
struct sshbuf *b;
struct stat st;
pid_t pid;
- int i, r, to[2], from[2], status, sock = packet_get_connection_in();
+ int i, r, to[2], from[2], status;
+ int sock = ssh_packet_get_connection_in(ssh);
u_char rversion = 0, version = 2;
void (*osigchld)(int);
*sigp = NULL;
*lenp = 0;
if (stat(_PATH_SSH_KEY_SIGN, &st) < 0) {
error("%s: not installed: %s", __func__, strerror(errno));
return -1;
}
if (fflush(stdout) != 0) {
error("%s: fflush: %s", __func__, strerror(errno));
return -1;
}
if (pipe(to) < 0) {
error("%s: pipe: %s", __func__, strerror(errno));
return -1;
}
if (pipe(from) < 0) {
error("%s: pipe: %s", __func__, strerror(errno));
return -1;
}
if ((pid = fork()) < 0) {
error("%s: fork: %s", __func__, strerror(errno));
return -1;
}
osigchld = signal(SIGCHLD, SIG_DFL);
if (pid == 0) {
/* keep the socket on exec */
fcntl(sock, F_SETFD, 0);
close(from[0]);
if (dup2(from[1], STDOUT_FILENO) < 0)
fatal("%s: dup2: %s", __func__, strerror(errno));
close(to[1]);
if (dup2(to[0], STDIN_FILENO) < 0)
fatal("%s: dup2: %s", __func__, strerror(errno));
close(from[1]);
close(to[0]);
/* Close everything but stdio and the socket */
for (i = STDERR_FILENO + 1; i < sock; i++)
close(i);
closefrom(sock + 1);
debug3("%s: [child] pid=%ld, exec %s",
__func__, (long)getpid(), _PATH_SSH_KEY_SIGN);
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *)NULL);
fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN,
strerror(errno));
}
close(from[1]);
close(to[0]);
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
/* send # of sock, data to be signed */
if ((r = sshbuf_put_u32(b, sock)) != 0 ||
(r = sshbuf_put_string(b, data, datalen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (ssh_msg_send(to[1], version, b) == -1)
fatal("%s: couldn't send request", __func__);
sshbuf_reset(b);
r = ssh_msg_recv(from[0], b);
close(from[0]);
close(to[1]);
if (r < 0) {
error("%s: no reply", __func__);
goto fail;
}
errno = 0;
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
error("%s: waitpid %ld: %s",
__func__, (long)pid, strerror(errno));
goto fail;
}
}
if (!WIFEXITED(status)) {
error("%s: exited abnormally", __func__);
goto fail;
}
if (WEXITSTATUS(status) != 0) {
error("%s: exited with status %d",
__func__, WEXITSTATUS(status));
goto fail;
}
if ((r = sshbuf_get_u8(b, &rversion)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
goto fail;
}
if (rversion != version) {
error("%s: bad version", __func__);
goto fail;
}
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
fail:
signal(SIGCHLD, osigchld);
sshbuf_free(b);
return -1;
}
signal(SIGCHLD, osigchld);
sshbuf_free(b);
return 0;
}
-int
-userauth_hostbased(Authctxt *authctxt)
+static int
+userauth_hostbased(struct ssh *ssh)
{
- struct ssh *ssh = active_state; /* XXX */
+ Authctxt *authctxt = (Authctxt *)ssh->authctxt;
struct sshkey *private = NULL;
struct sshbuf *b = NULL;
u_char *sig = NULL, *keyblob = NULL;
char *fp = NULL, *chost = NULL, *lname = NULL;
size_t siglen = 0, keylen = 0;
int i, r, success = 0;
if (authctxt->ktypes == NULL) {
authctxt->oktypes = xstrdup(options.hostbased_key_types);
authctxt->ktypes = authctxt->oktypes;
}
/*
* Work through each listed type pattern in HostbasedKeyTypes,
* trying each hostkey that matches the type in turn.
*/
for (;;) {
if (authctxt->active_ktype == NULL)
authctxt->active_ktype = strsep(&authctxt->ktypes, ",");
if (authctxt->active_ktype == NULL ||
*authctxt->active_ktype == '\0')
break;
debug3("%s: trying key type %s", __func__,
authctxt->active_ktype);
/* check for a useful key */
private = NULL;
for (i = 0; i < authctxt->sensitive->nkeys; i++) {
if (authctxt->sensitive->keys[i] == NULL ||
authctxt->sensitive->keys[i]->type == KEY_UNSPEC)
continue;
if (match_pattern_list(
sshkey_ssh_name(authctxt->sensitive->keys[i]),
authctxt->active_ktype, 0) != 1)
continue;
/* we take and free the key */
private = authctxt->sensitive->keys[i];
authctxt->sensitive->keys[i] = NULL;
break;
}
/* Found one */
if (private != NULL)
break;
/* No more keys of this type; advance */
authctxt->active_ktype = NULL;
}
if (private == NULL) {
free(authctxt->oktypes);
authctxt->oktypes = authctxt->ktypes = NULL;
authctxt->active_ktype = NULL;
debug("No more client hostkeys for hostbased authentication.");
goto out;
}
if ((fp = sshkey_fingerprint(private, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
error("%s: sshkey_fingerprint failed", __func__);
goto out;
}
debug("%s: trying hostkey %s %s",
__func__, sshkey_ssh_name(private), fp);
/* figure out a name for the client host */
- if ((lname = get_local_name(packet_get_connection_in())) == NULL) {
+ lname = get_local_name(ssh_packet_get_connection_in(ssh));
+ if (lname == NULL) {
error("%s: cannot get local ipaddr/name", __func__);
goto out;
}
/* XXX sshbuf_put_stringf? */
xasprintf(&chost, "%s.", lname);
debug2("%s: chost %s", __func__, chost);
/* construct data */
if ((b = sshbuf_new()) == NULL) {
error("%s: sshbuf_new failed", __func__);
goto out;
}
if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) {
error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
goto out;
}
if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
(r = sshbuf_put_cstring(b, sshkey_ssh_name(private))) != 0 ||
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 ||
(r = sshbuf_put_cstring(b, chost)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) {
error("%s: buffer error: %s", __func__, ssh_err(r));
goto out;
}
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
- r = ssh_keysign(private, &sig, &siglen,
- sshbuf_ptr(b), sshbuf_len(b));
- if (r != 0) {
+ if ((r = ssh_keysign(ssh, private, &sig, &siglen,
+ sshbuf_ptr(b), sshbuf_len(b))) != 0) {
error("sign using hostkey %s %s failed",
sshkey_ssh_name(private), fp);
goto out;
}
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_put_cstring(ssh, sshkey_ssh_name(private))) != 0 ||
(r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 ||
(r = sshpkt_put_cstring(ssh, chost)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 ||
(r = sshpkt_put_string(ssh, sig, siglen)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
error("%s: packet error: %s", __func__, ssh_err(r));
goto out;
}
success = 1;
out:
if (sig != NULL)
freezero(sig, siglen);
free(keyblob);
free(lname);
free(fp);
free(chost);
sshkey_free(private);
sshbuf_free(b);
return success;
}
/* find auth method */
/*
* given auth method name, if configurable options permit this method fill
* in auth_ident field and return true, otherwise return false.
*/
static int
authmethod_is_enabled(Authmethod *method)
{
if (method == NULL)
return 0;
/* return false if options indicate this method is disabled */
if (method->enabled == NULL || *method->enabled == 0)
return 0;
/* return false if batch mode is enabled but method needs interactive mode */
if (method->batch_flag != NULL && *method->batch_flag != 0)
return 0;
return 1;
}
static Authmethod *
authmethod_lookup(const char *name)
{
Authmethod *method = NULL;
if (name != NULL)
for (method = authmethods; method->name != NULL; method++)
if (strcmp(name, method->name) == 0)
return method;
debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
return NULL;
}
/* XXX internal state */
static Authmethod *current = NULL;
static char *supported = NULL;
static char *preferred = NULL;
/*
* Given the authentication method list sent by the server, return the
* next method we should try. If the server initially sends a nil list,
* use a built-in default list.
*/
static Authmethod *
authmethod_get(char *authlist)
{
char *name = NULL;
u_int next;
/* Use a suitable default if we're passed a nil list. */
if (authlist == NULL || strlen(authlist) == 0)
authlist = options.preferred_authentications;
if (supported == NULL || strcmp(authlist, supported) != 0) {
debug3("start over, passed a different list %s", authlist);
free(supported);
supported = xstrdup(authlist);
preferred = options.preferred_authentications;
debug3("preferred %s", preferred);
current = NULL;
} else if (current != NULL && authmethod_is_enabled(current))
return current;
for (;;) {
if ((name = match_list(preferred, supported, &next)) == NULL) {
debug("No more authentication methods to try.");
current = NULL;
return NULL;
}
preferred += next;
debug3("authmethod_lookup %s", name);
debug3("remaining preferred: %s", preferred);
if ((current = authmethod_lookup(name)) != NULL &&
authmethod_is_enabled(current)) {
debug3("authmethod_is_enabled %s", name);
debug("Next authentication method: %s", name);
free(name);
return current;
}
free(name);
}
}
static char *
authmethods_get(void)
{
Authmethod *method = NULL;
struct sshbuf *b;
char *list;
int r;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
for (method = authmethods; method->name != NULL; method++) {
if (authmethod_is_enabled(method)) {
if ((r = sshbuf_putf(b, "%s%s",
sshbuf_len(b) ? "," : "", method->name)) != 0)
fatal("%s: buffer error: %s",
__func__, ssh_err(r));
}
}
if ((list = sshbuf_dup_string(b)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
sshbuf_free(b);
return list;
}
diff --git a/sshd.0 b/sshd.0
index ac7e70707113..da8539aef6c2 100644
--- a/sshd.0
+++ b/sshd.0
@@ -1,653 +1,653 @@
SSHD(8) System Manager's Manual SSHD(8)
NAME
sshd M-bM-^@M-^S OpenSSH SSH daemon
SYNOPSIS
sshd [-46DdeiqTt] [-C connection_spec] [-c host_certificate_file]
[-E log_file] [-f config_file] [-g login_grace_time]
[-h host_key_file] [-o option] [-p port] [-u len]
DESCRIPTION
sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these
programs replace rlogin and rsh, and provide secure encrypted
communications between two untrusted hosts over an insecure network.
sshd listens for connections from clients. It is normally started at
boot from /etc/rc. It forks a new daemon for each incoming connection.
The forked daemons handle key exchange, encryption, authentication,
command execution, and data exchange.
sshd can be configured using command-line options or a configuration file
(by default sshd_config(5)); command-line options override values
specified in the configuration file. sshd rereads its configuration file
when it receives a hangup signal, SIGHUP, by executing itself with the
name and options it was started with, e.g. /usr/sbin/sshd.
The options are as follows:
-4 Forces sshd to use IPv4 addresses only.
-6 Forces sshd to use IPv6 addresses only.
-C connection_spec
Specify the connection parameters to use for the -T extended test
mode. If provided, any Match directives in the configuration
file that would apply are applied before the configuration is
written to standard output. The connection parameters are
supplied as keyword=value pairs and may be supplied in any order,
either with multiple -C options or as a comma-separated list.
The keywords are M-bM-^@M-^\addr,M-bM-^@M-^] M-bM-^@M-^\userM-bM-^@M-^], M-bM-^@M-^\hostM-bM-^@M-^], M-bM-^@M-^\laddrM-bM-^@M-^], M-bM-^@M-^\lportM-bM-^@M-^], and
M-bM-^@M-^\rdomainM-bM-^@M-^] and correspond to source address, user, resolved source
host name, local address, local port number and routing domain
respectively.
-c host_certificate_file
Specifies a path to a certificate file to identify sshd during
key exchange. The certificate file must match a host key file
specified using the -h option or the HostKey configuration
directive.
-D When this option is specified, sshd will not detach and does not
become a daemon. This allows easy monitoring of sshd.
-d Debug mode. The server sends verbose debug output to standard
error, and does not put itself in the background. The server
also will not fork and will only process one connection. This
option is only intended for debugging for the server. Multiple
-d options increase the debugging level. Maximum is 3.
-E log_file
Append debug logs to log_file instead of the system log.
-e Write debug logs to standard error instead of the system log.
-f config_file
Specifies the name of the configuration file. The default is
/etc/ssh/sshd_config. sshd refuses to start if there is no
configuration file.
-g login_grace_time
Gives the grace time for clients to authenticate themselves
(default 120 seconds). If the client fails to authenticate the
user within this many seconds, the server disconnects and exits.
A value of zero indicates no limit.
-h host_key_file
Specifies a file from which a host key is read. This option must
be given if sshd is not run as root (as the normal host key files
are normally not readable by anyone but root). The default is
/etc/ssh/ssh_host_ecdsa_key, /etc/ssh/ssh_host_ed25519_key and
/etc/ssh/ssh_host_rsa_key. It is possible to have multiple host
key files for the different host key algorithms.
-i Specifies that sshd is being run from inetd(8).
-o option
Can be used to give options in the format used in the
configuration file. This is useful for specifying options for
which there is no separate command-line flag. For full details
of the options, and their values, see sshd_config(5).
-p port
Specifies the port on which the server listens for connections
(default 22). Multiple port options are permitted. Ports
specified in the configuration file with the Port option are
ignored when a command-line port is specified. Ports specified
using the ListenAddress option override command-line ports.
-q Quiet mode. Nothing is sent to the system log. Normally the
beginning, authentication, and termination of each connection is
logged.
-T Extended test mode. Check the validity of the configuration
file, output the effective configuration to stdout and then exit.
Optionally, Match rules may be applied by specifying the
connection parameters using one or more -C options.
-t Test mode. Only check the validity of the configuration file and
sanity of the keys. This is useful for updating sshd reliably as
configuration options may change.
-u len This option is used to specify the size of the field in the utmp
structure that holds the remote host name. If the resolved host
name is longer than len, the dotted decimal value will be used
instead. This allows hosts with very long host names that
overflow this field to still be uniquely identified. Specifying
-u0 indicates that only dotted decimal addresses should be put
into the utmp file. -u0 may also be used to prevent sshd from
making DNS requests unless the authentication mechanism or
configuration requires it. Authentication mechanisms that may
require DNS include HostbasedAuthentication and using a
from="pattern-list" option in a key file. Configuration options
that require DNS include using a USER@HOST pattern in AllowUsers
or DenyUsers.
AUTHENTICATION
The OpenSSH SSH daemon supports SSH protocol 2 only. Each host has a
host-specific key, used to identify the host. Whenever a client
connects, the daemon responds with its public host key. The client
compares the host key against its own database to verify that it has not
changed. Forward security is provided through a Diffie-Hellman key
agreement. This key agreement results in a shared session key. The rest
of the session is encrypted using a symmetric cipher, currently 128-bit
AES, Blowfish, 3DES, CAST128, Arcfour, 192-bit AES, or 256-bit AES. The
client selects the encryption algorithm to use from those offered by the
server. Additionally, session integrity is provided through a
cryptographic message authentication code (hmac-md5, hmac-sha1, umac-64,
umac-128, hmac-sha2-256 or hmac-sha2-512).
Finally, the server and the client enter an authentication dialog. The
client tries to authenticate itself using host-based authentication,
public key authentication, challenge-response authentication, or password
authentication.
Regardless of the authentication type, the account is checked to ensure
that it is accessible. An account is not accessible if it is locked,
listed in DenyUsers or its group is listed in DenyGroups . The
definition of a locked account is system dependent. Some platforms have
their own account database (eg AIX) and some modify the passwd field (
M-bM-^@M-^X*LK*M-bM-^@M-^Y on Solaris and UnixWare, M-bM-^@M-^X*M-bM-^@M-^Y on HP-UX, containing M-bM-^@M-^XNologinM-bM-^@M-^Y on
Tru64, a leading M-bM-^@M-^X*LOCKED*M-bM-^@M-^Y on FreeBSD and a leading M-bM-^@M-^X!M-bM-^@M-^Y on most
Linuxes). If there is a requirement to disable password authentication
for the account while allowing still public-key, then the passwd field
should be set to something other than these values (eg M-bM-^@M-^XNPM-bM-^@M-^Y or M-bM-^@M-^X*NP*M-bM-^@M-^Y ).
If the client successfully authenticates itself, a dialog for preparing
the session is entered. At this time the client may request things like
allocating a pseudo-tty, forwarding X11 connections, forwarding TCP
connections, or forwarding the authentication agent connection over the
secure channel.
After this, the client either requests a shell or execution of a command.
The sides then enter session mode. In this mode, either side may send
data at any time, and such data is forwarded to/from the shell or command
on the server side, and the user terminal in the client side.
When the user program terminates and all forwarded X11 and other
connections have been closed, the server sends command exit status to the
client, and both sides exit.
LOGIN PROCESS
When a user successfully logs in, sshd does the following:
1. If the login is on a tty, and no command has been specified,
prints last login time and /etc/motd (unless prevented in the
configuration file or by ~/.hushlogin; see the FILES section).
2. If the login is on a tty, records login time.
3. Checks /etc/nologin; if it exists, prints contents and quits
(unless root).
4. Changes to run with normal user privileges.
5. Sets up basic environment.
6. Reads the file ~/.ssh/environment, if it exists, and users are
allowed to change their environment. See the
PermitUserEnvironment option in sshd_config(5).
7. Changes to user's home directory.
8. If ~/.ssh/rc exists and the sshd_config(5) PermitUserRC option
is set, runs it; else if /etc/ssh/sshrc exists, runs it;
otherwise runs xauth. The M-bM-^@M-^\rcM-bM-^@M-^] files are given the X11
authentication protocol and cookie in standard input. See
SSHRC, below.
9. Runs user's shell or command. All commands are run under the
user's login shell as specified in the system password
database.
SSHRC
If the file ~/.ssh/rc exists, sh(1) runs it after reading the environment
files but before starting the user's shell or command. It must not
produce any output on stdout; stderr must be used instead. If X11
forwarding is in use, it will receive the "proto cookie" pair in its
standard input (and DISPLAY in its environment). The script must call
xauth(1) because sshd will not run xauth automatically to add X11
cookies.
The primary purpose of this file is to run any initialization routines
which may be needed before the user's home directory becomes accessible;
AFS is a particular example of such an environment.
This file will probably contain some initialization code followed by
something similar to:
if read proto cookie && [ -n "$DISPLAY" ]; then
if [ `echo $DISPLAY | cut -c1-10` = 'localhost:' ]; then
# X11UseLocalhost=yes
echo add unix:`echo $DISPLAY |
cut -c11-` $proto $cookie
else
# X11UseLocalhost=no
echo add $DISPLAY $proto $cookie
fi | xauth -q -
fi
If this file does not exist, /etc/ssh/sshrc is run, and if that does not
exist either, xauth is used to add the cookie.
AUTHORIZED_KEYS FILE FORMAT
AuthorizedKeysFile specifies the files containing public keys for public
key authentication; if this option is not specified, the default is
~/.ssh/authorized_keys and ~/.ssh/authorized_keys2. Each line of the
file contains one key (empty lines and lines starting with a M-bM-^@M-^X#M-bM-^@M-^Y are
ignored as comments). Public keys consist of the following space-
separated fields: options, keytype, base64-encoded key, comment. The
options field is optional. The keytype is M-bM-^@M-^\ecdsa-sha2-nistp256M-bM-^@M-^],
M-bM-^@M-^\ecdsa-sha2-nistp384M-bM-^@M-^], M-bM-^@M-^\ecdsa-sha2-nistp521M-bM-^@M-^], M-bM-^@M-^\ssh-ed25519M-bM-^@M-^], M-bM-^@M-^\ssh-dssM-bM-^@M-^] or
M-bM-^@M-^\ssh-rsaM-bM-^@M-^]; the comment field is not used for anything (but may be
convenient for the user to identify the key).
Note that lines in this file can be several hundred bytes long (because
of the size of the public key encoding) up to a limit of 8 kilobytes,
which permits DSA keys up to 8 kilobits and RSA keys up to 16 kilobits.
You don't want to type them in; instead, copy the id_dsa.pub,
id_ecdsa.pub, id_ed25519.pub, or the id_rsa.pub file and edit it.
sshd enforces a minimum RSA key modulus size of 1024 bits.
The options (if present) consist of comma-separated option
specifications. No spaces are permitted, except within double quotes.
The following option specifications are supported (note that option
keywords are case-insensitive):
agent-forwarding
Enable authentication agent forwarding previously disabled by the
restrict option.
cert-authority
Specifies that the listed key is a certification authority (CA)
that is trusted to validate signed certificates for user
authentication.
Certificates may encode access restrictions similar to these key
options. If both certificate restrictions and key options are
present, the most restrictive union of the two is applied.
command="command"
Specifies that the command is executed whenever this key is used
for authentication. The command supplied by the user (if any) is
ignored. The command is run on a pty if the client requests a
pty; otherwise it is run without a tty. If an 8-bit clean
channel is required, one must not request a pty or should specify
no-pty. A quote may be included in the command by quoting it
with a backslash.
This option might be useful to restrict certain public keys to
perform just a specific operation. An example might be a key
that permits remote backups but nothing else. Note that the
client may specify TCP and/or X11 forwarding unless they are
explicitly prohibited, e.g. using the restrict key option.
The command originally supplied by the client is available in the
SSH_ORIGINAL_COMMAND environment variable. Note that this option
applies to shell, command or subsystem execution. Also note that
this command may be superseded by a sshd_config(5) ForceCommand
directive.
If a command is specified and a forced-command is embedded in a
certificate used for authentication, then the certificate will be
accepted only if the two commands are identical.
environment="NAME=value"
Specifies that the string is to be added to the environment when
logging in using this key. Environment variables set this way
override other default environment values. Multiple options of
this type are permitted. Environment processing is disabled by
default and is controlled via the PermitUserEnvironment option.
expiry-time="timespec"
Specifies a time after which the key will not be accepted. The
time may be specified as a YYYYMMDD date or a YYYYMMDDHHMM[SS]
time in the system time-zone.
from="pattern-list"
Specifies that in addition to public key authentication, either
the canonical name of the remote host or its IP address must be
present in the comma-separated list of patterns. See PATTERNS in
ssh_config(5) for more information on patterns.
In addition to the wildcard matching that may be applied to
hostnames or addresses, a from stanza may match IP addresses
using CIDR address/masklen notation.
The purpose of this option is to optionally increase security:
public key authentication by itself does not trust the network or
name servers or anything (but the key); however, if somebody
somehow steals the key, the key permits an intruder to log in
from anywhere in the world. This additional option makes using a
stolen key more difficult (name servers and/or routers would have
to be compromised in addition to just the key).
no-agent-forwarding
Forbids authentication agent forwarding when this key is used for
authentication.
no-port-forwarding
Forbids TCP forwarding when this key is used for authentication.
Any port forward requests by the client will return an error.
This might be used, e.g. in connection with the command option.
no-pty Prevents tty allocation (a request to allocate a pty will fail).
no-user-rc
Disables execution of ~/.ssh/rc.
no-X11-forwarding
Forbids X11 forwarding when this key is used for authentication.
Any X11 forward requests by the client will return an error.
permitlisten="[host:]port"
Limit remote port forwarding with the ssh(1) -R option such that
it may only listen on the specified host (optional) and port.
IPv6 addresses can be specified by enclosing the address in
square brackets. Multiple permitlisten options may be applied
separated by commas. Hostnames may include wildcards as
described in the PATTERNS section in ssh_config(5). A port
specification of * matches any port. Note that the setting of
GatewayPorts may further restrict listen addresses. Note that
ssh(1) will send a hostname of M-bM-^@M-^\localhostM-bM-^@M-^] if a listen host was
not specified when the forwarding was requested, and that this
name is treated differently to the explicit localhost addresses
M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and M-bM-^@M-^\::1M-bM-^@M-^].
permitopen="host:port"
Limit local port forwarding with the ssh(1) -L option such that
it may only connect to the specified host and port. IPv6
addresses can be specified by enclosing the address in square
brackets. Multiple permitopen options may be applied separated
by commas. No pattern matching is performed on the specified
hostnames, they must be literal domains or addresses. A port
specification of * matches any port.
port-forwarding
Enable port forwarding previously disabled by the restrict
option.
principals="principals"
On a cert-authority line, specifies allowed principals for
certificate authentication as a comma-separated list. At least
one name from the list must appear in the certificate's list of
principals for the certificate to be accepted. This option is
ignored for keys that are not marked as trusted certificate
signers using the cert-authority option.
pty Permits tty allocation previously disabled by the restrict
option.
restrict
Enable all restrictions, i.e. disable port, agent and X11
forwarding, as well as disabling PTY allocation and execution of
~/.ssh/rc. If any future restriction capabilities are added to
authorized_keys files they will be included in this set.
tunnel="n"
Force a tun(4) device on the server. Without this option, the
next available device will be used if the client requests a
tunnel.
user-rc
Enables execution of ~/.ssh/rc previously disabled by the
restrict option.
X11-forwarding
Permits X11 forwarding previously disabled by the restrict
option.
An example authorized_keys file:
# Comments allowed at start of line
ssh-rsa AAAAB3Nza...LiPk== user@example.net
from="*.sales.example.net,!pc.sales.example.net" ssh-rsa
AAAAB2...19Q== john@example.net
command="dump /home",no-pty,no-port-forwarding ssh-rsa
AAAAC3...51R== example.net
permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa
AAAAB5...21S==
permitlisten="localhost:8080",permitopen="localhost:22000" ssh-rsa
AAAAB5...21S==
tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...==
jane@example.net
restrict,command="uptime" ssh-rsa AAAA1C8...32Tv==
user@example.net
restrict,pty,command="nethack" ssh-rsa AAAA1f8...IrrC5==
user@example.net
SSH_KNOWN_HOSTS FILE FORMAT
The /etc/ssh/ssh_known_hosts and ~/.ssh/known_hosts files contain host
public keys for all known hosts. The global file should be prepared by
the administrator (optional), and the per-user file is maintained
automatically: whenever the user connects to an unknown host, its key is
added to the per-user file.
Each line in these files contains the following fields: markers
(optional), hostnames, keytype, base64-encoded key, comment. The fields
are separated by spaces.
The marker is optional, but if it is present then it must be one of
M-bM-^@M-^\@cert-authorityM-bM-^@M-^], to indicate that the line contains a certification
authority (CA) key, or M-bM-^@M-^\@revokedM-bM-^@M-^], to indicate that the key contained on
the line is revoked and must not ever be accepted. Only one marker
should be used on a key line.
Hostnames is a comma-separated list of patterns (M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y act as
wildcards); each pattern in turn is matched against the host name. When
sshd is authenticating a client, such as when using
HostbasedAuthentication, this will be the canonical client host name.
When ssh(1) is authenticating a server, this will be the host name given
by the user, the value of the ssh(1) HostkeyAlias if it was specified, or
the canonical server hostname if the ssh(1) CanonicalizeHostname option
was used.
A pattern may also be preceded by M-bM-^@M-^X!M-bM-^@M-^Y to indicate negation: if the host
name matches a negated pattern, it is not accepted (by that line) even if
it matched another pattern on the line. A hostname or address may
optionally be enclosed within M-bM-^@M-^X[M-bM-^@M-^Y and M-bM-^@M-^X]M-bM-^@M-^Y brackets then followed by M-bM-^@M-^X:M-bM-^@M-^Y
and a non-standard port number.
Alternately, hostnames may be stored in a hashed form which hides host
names and addresses should the file's contents be disclosed. Hashed
hostnames start with a M-bM-^@M-^X|M-bM-^@M-^Y character. Only one hashed hostname may
appear on a single line and none of the above negation or wildcard
operators may be applied.
The keytype and base64-encoded key are taken directly from the host key;
they can be obtained, for example, from /etc/ssh/ssh_host_rsa_key.pub.
The optional comment field continues to the end of the line, and is not
used.
Lines starting with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines are ignored as comments.
When performing host authentication, authentication is accepted if any
matching line has the proper key; either one that matches exactly or, if
the server has presented a certificate for authentication, the key of the
certification authority that signed the certificate. For a key to be
trusted as a certification authority, it must use the M-bM-^@M-^\@cert-authorityM-bM-^@M-^]
marker described above.
The known hosts file also provides a facility to mark keys as revoked,
for example when it is known that the associated private key has been
stolen. Revoked keys are specified by including the M-bM-^@M-^\@revokedM-bM-^@M-^] marker at
the beginning of the key line, and are never accepted for authentication
or as certification authorities, but instead will produce a warning from
ssh(1) when they are encountered.
It is permissible (but not recommended) to have several lines or
different host keys for the same names. This will inevitably happen when
short forms of host names from different domains are put in the file. It
is possible that the files contain conflicting information;
authentication is accepted if valid information can be found from either
file.
Note that the lines in these files are typically hundreds of characters
long, and you definitely don't want to type in the host keys by hand.
Rather, generate them by a script, ssh-keyscan(1) or by taking, for
example, /etc/ssh/ssh_host_rsa_key.pub and adding the host names at the
front. ssh-keygen(1) also offers some basic automated editing for
~/.ssh/known_hosts including removing hosts matching a host name and
converting all host names to their hashed representations.
An example ssh_known_hosts file:
# Comments allowed at start of line
closenet,...,192.0.2.53 1024 37 159...93 closenet.example.net
cvs.example.net,192.0.2.10 ssh-rsa AAAA1234.....=
# A hashed hostname
|1|JfKTdBh7rNbXkVAQCRp4OQoPfmI=|USECr3SWf1JUPsms5AqfD5QfxkM= ssh-rsa
AAAA1234.....=
# A revoked key
@revoked * ssh-rsa AAAAB5W...
# A CA key, accepted for any host in *.mydomain.com or *.mydomain.org
@cert-authority *.mydomain.org,*.mydomain.com ssh-rsa AAAAB5W...
FILES
~/.hushlogin
This file is used to suppress printing the last login time and
/etc/motd, if PrintLastLog and PrintMotd, respectively, are
enabled. It does not suppress printing of the banner specified
by Banner.
~/.rhosts
This file is used for host-based authentication (see ssh(1) for
more information). On some machines this file may need to be
world-readable if the user's home directory is on an NFS
partition, because sshd reads it as root. Additionally, this
file must be owned by the user, and must not have write
permissions for anyone else. The recommended permission for most
machines is read/write for the user, and not accessible by
others.
~/.shosts
This file is used in exactly the same way as .rhosts, but allows
host-based authentication without permitting login with
rlogin/rsh.
~/.ssh/
This directory is the default location for all user-specific
configuration and authentication information. There is no
general requirement to keep the entire contents of this directory
secret, but the recommended permissions are read/write/execute
for the user, and not accessible by others.
~/.ssh/authorized_keys
Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used
for logging in as this user. The format of this file is
described above. The content of the file is not highly
sensitive, but the recommended permissions are read/write for the
user, and not accessible by others.
If this file, the ~/.ssh directory, or the user's home directory
are writable by other users, then the file could be modified or
replaced by unauthorized users. In this case, sshd will not
allow it to be used unless the StrictModes option has been set to
M-bM-^@M-^\noM-bM-^@M-^].
~/.ssh/environment
This file is read into the environment at login (if it exists).
It can only contain empty lines, comment lines (that start with
M-bM-^@M-^X#M-bM-^@M-^Y), and assignment lines of the form name=value. The file
should be writable only by the user; it need not be readable by
anyone else. Environment processing is disabled by default and
is controlled via the PermitUserEnvironment option.
~/.ssh/known_hosts
Contains a list of host keys for all hosts the user has logged
into that are not already in the systemwide list of known host
keys. The format of this file is described above. This file
should be writable only by root/the owner and can, but need not
be, world-readable.
~/.ssh/rc
Contains initialization routines to be run before the user's home
directory becomes accessible. This file should be writable only
by the user, and need not be readable by anyone else.
/etc/hosts.equiv
This file is for host-based authentication (see ssh(1)). It
should only be writable by root.
/etc/moduli
Contains Diffie-Hellman groups used for the "Diffie-Hellman Group
Exchange" key exchange method. The file format is described in
moduli(5). If no usable groups are found in this file then fixed
internal groups will be used.
/etc/motd
See motd(5).
/etc/nologin
If this file exists, sshd refuses to let anyone except root log
in. The contents of the file are displayed to anyone trying to
log in, and non-root connections are refused. The file should be
world-readable.
/etc/shosts.equiv
This file is used in exactly the same way as hosts.equiv, but
allows host-based authentication without permitting login with
rlogin/rsh.
/etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_rsa_key
These files contain the private parts of the host keys. These
files should only be owned by root, readable only by root, and
not accessible to others. Note that sshd does not start if these
files are group/world-accessible.
/etc/ssh/ssh_host_ecdsa_key.pub
/etc/ssh/ssh_host_ed25519_key.pub
/etc/ssh/ssh_host_rsa_key.pub
These files contain the public parts of the host keys. These
files should be world-readable but writable only by root. Their
contents should match the respective private parts. These files
are not really used for anything; they are provided for the
convenience of the user so their contents can be copied to known
hosts files. These files are created using ssh-keygen(1).
/etc/ssh/ssh_known_hosts
Systemwide list of known host keys. This file should be prepared
by the system administrator to contain the public host keys of
all machines in the organization. The format of this file is
described above. This file should be writable only by root/the
owner and should be world-readable.
/etc/ssh/sshd_config
Contains configuration data for sshd. The file format and
configuration options are described in sshd_config(5).
/etc/ssh/sshrc
Similar to ~/.ssh/rc, it can be used to specify machine-specific
login-time initializations globally. This file should be
writable only by root, and should be world-readable.
/var/empty
chroot(2) directory used by sshd during privilege separation in
the pre-authentication phase. The directory should not contain
any files and must be owned by root and not group or world-
writable.
/var/run/sshd.pid
Contains the process ID of the sshd listening for connections (if
there are several daemons running concurrently for different
ports, this contains the process ID of the one started last).
The content of this file is not sensitive; it can be world-
readable.
SEE ALSO
scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1),
ssh-keyscan(1), chroot(2), login.conf(5), moduli(5), sshd_config(5),
inetd(8), sftp-server(8)
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support
for privilege separation.
-OpenBSD 6.4 July 22, 2018 OpenBSD 6.4
+OpenBSD 6.5 July 22, 2018 OpenBSD 6.5
diff --git a/sshd.c b/sshd.c
index ba26287ba040..cbd3bce913ec 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,2353 +1,2322 @@
-/* $OpenBSD: sshd.c,v 1.516 2018/09/21 12:23:17 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.533 2019/03/01 02:32:39 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* This program is the ssh daemon. It listens for connections from clients,
* and performs authentication, executes use commands or shell, and forwards
* information to/from the application to the user client over an encrypted
* connection. This can also handle forwarding of X11, TCP/IP, and
* authentication agent connections.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* SSH2 implementation:
* Privilege Separation:
*
* Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved.
* Copyright (c) 2002 Niels Provos. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include "openbsd-compat/sys-tree.h"
#include "openbsd-compat/sys-queue.h"
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#ifdef WITH_OPENSSL
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include "openbsd-compat/openssl-compat.h"
#endif
#ifdef HAVE_SECUREWARE
#include <sys/security.h>
#include <prot.h>
#endif
#include "xmalloc.h"
#include "ssh.h"
#include "ssh2.h"
#include "sshpty.h"
#include "packet.h"
#include "log.h"
#include "sshbuf.h"
#include "misc.h"
#include "match.h"
#include "servconf.h"
#include "uidswap.h"
#include "compat.h"
#include "cipher.h"
#include "digest.h"
#include "sshkey.h"
#include "kex.h"
#include "myproposal.h"
#include "authfile.h"
#include "pathnames.h"
#include "atomicio.h"
#include "canohost.h"
#include "hostfile.h"
#include "auth.h"
#include "authfd.h"
#include "msg.h"
#include "dispatch.h"
#include "channels.h"
#include "session.h"
#include "monitor.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "ssh-sandbox.h"
#include "auth-options.h"
#include "version.h"
#include "ssherr.h"
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
#define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
#define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3)
#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4)
extern char *__progname;
/* Server configuration options. */
ServerOptions options;
/* Name of the server configuration file. */
char *config_file_name = _PATH_SERVER_CONFIG_FILE;
/*
* Debug mode flag. This can be set on the command line. If debug
* mode is enabled, extra debugging output will be sent to the system
* log, the daemon will not go to background, and will exit after processing
* the first connection.
*/
int debug_flag = 0;
/*
* Indicating that the daemon should only test the configuration and keys.
* If test_flag > 1 ("-T" flag), then sshd will also dump the effective
* configuration, optionally using connection information provided by the
* "-C" flag.
*/
-int test_flag = 0;
+static int test_flag = 0;
/* Flag indicating that the daemon is being started from inetd. */
-int inetd_flag = 0;
+static int inetd_flag = 0;
/* Flag indicating that sshd should not detach and become a daemon. */
-int no_daemon_flag = 0;
+static int no_daemon_flag = 0;
/* debug goes to stderr unless inetd_flag is set */
-int log_stderr = 0;
+static int log_stderr = 0;
/* Saved arguments to main(). */
-char **saved_argv;
-int saved_argc;
+static char **saved_argv;
+static int saved_argc;
/* re-exec */
-int rexeced_flag = 0;
-int rexec_flag = 1;
-int rexec_argc = 0;
-char **rexec_argv;
+static int rexeced_flag = 0;
+static int rexec_flag = 1;
+static int rexec_argc = 0;
+static char **rexec_argv;
/*
* The sockets that the server is listening; this is used in the SIGHUP
* signal handler.
*/
#define MAX_LISTEN_SOCKS 16
-int listen_socks[MAX_LISTEN_SOCKS];
-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;
+static int listen_socks[MAX_LISTEN_SOCKS];
+static int num_listen_socks = 0;
/* Daemon's agent connection */
int auth_sock = -1;
-int have_agent = 0;
+static int have_agent = 0;
/*
* Any really sensitive data in the application is contained in this
* structure. The idea is that this structure could be locked into memory so
* that the pages do not get written into swap. However, there are some
* problems. The private key contains BIGNUMs, and we do not (in principle)
* have access to the internals of them, and locking just the structure is
* not very useful. Currently, memory locking is not implemented.
*/
struct {
struct sshkey **host_keys; /* all private host keys */
struct sshkey **host_pubkeys; /* all public host keys */
struct sshkey **host_certificates; /* all public host certificates */
int have_ssh2_key;
} sensitive_data;
/* This is set to true when a signal is received. */
static volatile sig_atomic_t received_sighup = 0;
static volatile sig_atomic_t received_sigterm = 0;
/* session identifier, used by RSA-auth */
u_char session_id[16];
/* same for ssh2 */
u_char *session_id2 = NULL;
u_int session_id2_len = 0;
/* record remote hostname or ip */
u_int utmp_len = HOST_NAME_MAX+1;
-/* options.max_startup sized array of fd ints */
-int *startup_pipes = NULL;
-int startup_pipe; /* in child */
+/*
+ * startup_pipes/flags are used for tracking children of the listening sshd
+ * process early in their lifespans. This tracking is needed for three things:
+ *
+ * 1) Implementing the MaxStartups limit of concurrent unauthenticated
+ * connections.
+ * 2) Avoiding a race condition for SIGHUP processing, where child processes
+ * may have listen_socks open that could collide with main listener process
+ * after it restarts.
+ * 3) Ensuring that rexec'd sshd processes have received their initial state
+ * from the parent listen process before handling SIGHUP.
+ *
+ * Child processes signal that they have completed closure of the listen_socks
+ * and (if applicable) received their rexec state by sending a char over their
+ * sock. Child processes signal that authentication has completed by closing
+ * the sock (or by exiting).
+ */
+static int *startup_pipes = NULL;
+static int *startup_flags = NULL; /* Indicates child closed listener */
+static int startup_pipe = -1; /* in child */
/* variables used for privilege separation */
int use_privsep = -1;
struct monitor *pmonitor = NULL;
int privsep_is_preauth = 1;
static int privsep_chroot = 1;
-/* global authentication context */
+/* global connection state and authentication contexts */
Authctxt *the_authctxt = NULL;
+struct ssh *the_active_state;
/* global key/cert auth options. XXX move to permanent ssh->authctxt? */
struct sshauthopt *auth_opts = NULL;
/* sshd_config buffer */
struct sshbuf *cfg;
/* message to be displayed after login */
struct sshbuf *loginmsg;
/* Unprivileged user */
struct passwd *privsep_pw = NULL;
/* Prototypes for various functions defined later in this file. */
void destroy_sensitive_data(void);
void demote_sensitive_data(void);
-static void do_ssh2_kex(void);
+static void do_ssh2_kex(struct ssh *);
/*
* Close all listening sockets
*/
static void
close_listen_socks(void)
{
int i;
for (i = 0; i < num_listen_socks; i++)
close(listen_socks[i]);
num_listen_socks = -1;
}
static void
close_startup_pipes(void)
{
int i;
if (startup_pipes)
for (i = 0; i < options.max_startups; i++)
if (startup_pipes[i] != -1)
close(startup_pipes[i]);
}
/*
* Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
* the effect is to reread the configuration file (and to regenerate
* the server key).
*/
/*ARGSUSED*/
static void
sighup_handler(int sig)
{
int save_errno = errno;
received_sighup = 1;
errno = save_errno;
}
/*
* Called from the main program after receiving SIGHUP.
* Restarts the server.
*/
static void
sighup_restart(void)
{
logit("Received SIGHUP; restarting.");
if (options.pid_file != NULL)
unlink(options.pid_file);
platform_pre_restart();
close_listen_socks();
close_startup_pipes();
alarm(0); /* alarm timer persists across exec */
signal(SIGHUP, SIG_IGN); /* will be restored after exec */
execv(saved_argv[0], saved_argv);
logit("RESTART FAILED: av[0]='%.100s', error: %.100s.", saved_argv[0],
strerror(errno));
exit(1);
}
/*
* Generic signal handler for terminating signals in the master daemon.
*/
/*ARGSUSED*/
static void
sigterm_handler(int sig)
{
received_sigterm = sig;
}
/*
* SIGCHLD handler. This is called whenever a child dies. This will then
* reap any zombies left by exited children.
*/
/*ARGSUSED*/
static void
main_sigchld_handler(int sig)
{
int save_errno = errno;
pid_t pid;
int status;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR))
;
errno = save_errno;
}
/*
* Signal handler for the alarm after the login grace period has expired.
*/
/*ARGSUSED*/
static void
grace_alarm_handler(int sig)
{
if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
kill(pmonitor->m_pid, SIGALRM);
/*
* Try to kill any processes that we have spawned, E.g. authorized
* keys command helpers.
*/
if (getpgid(0) == getpid()) {
signal(SIGTERM, SIG_IGN);
kill(0, SIGTERM);
}
+ /* XXX pre-format ipaddr/port so we don't need to access active_state */
/* Log error and exit. */
sigdie("Timeout before authentication for %s port %d",
- 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);
- }
+ ssh_remote_ipaddr(the_active_state),
+ ssh_remote_port(the_active_state));
}
/* Destroy the host and server keys. They will no longer be needed. */
void
destroy_sensitive_data(void)
{
u_int i;
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
sshkey_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = NULL;
}
if (sensitive_data.host_certificates[i]) {
sshkey_free(sensitive_data.host_certificates[i]);
sensitive_data.host_certificates[i] = NULL;
}
}
}
/* Demote private to public keys for network child */
void
demote_sensitive_data(void)
{
struct sshkey *tmp;
u_int i;
int r;
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
if ((r = sshkey_from_private(
sensitive_data.host_keys[i], &tmp)) != 0)
fatal("could not demote host %s key: %s",
sshkey_type(sensitive_data.host_keys[i]),
ssh_err(r));
sshkey_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = tmp;
}
/* Certs do not need demotion */
}
}
static void
reseed_prngs(void)
{
u_int32_t rnd[256];
#ifdef WITH_OPENSSL
RAND_poll();
#endif
arc4random_stir(); /* noop on recent arc4random() implementations */
arc4random_buf(rnd, sizeof(rnd)); /* let arc4random notice PID change */
#ifdef WITH_OPENSSL
RAND_seed(rnd, sizeof(rnd));
/* give libcrypto a chance to notice the PID change */
if ((RAND_bytes((u_char *)rnd, 1)) != 1)
fatal("%s: RAND_bytes failed", __func__);
#endif
explicit_bzero(rnd, sizeof(rnd));
}
static void
privsep_preauth_child(void)
{
gid_t gidset[1];
/* Enable challenge-response authentication for privilege separation */
privsep_challenge_enable();
#ifdef GSSAPI
/* Cache supported mechanism OIDs for later use */
ssh_gssapi_prepare_supported_oids();
#endif
reseed_prngs();
/* Demote the private keys to public keys. */
demote_sensitive_data();
/* Demote the child */
if (privsep_chroot) {
/* Change our root directory */
if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
strerror(errno));
if (chdir("/") == -1)
fatal("chdir(\"/\"): %s", strerror(errno));
/* Drop our privileges */
debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid,
(u_int)privsep_pw->pw_gid);
gidset[0] = privsep_pw->pw_gid;
if (setgroups(1, gidset) < 0)
fatal("setgroups: %.100s", strerror(errno));
permanently_set_uid(privsep_pw);
}
}
static int
-privsep_preauth(Authctxt *authctxt)
+privsep_preauth(struct ssh *ssh)
{
int status, r;
pid_t pid;
struct ssh_sandbox *box = NULL;
/* Set up unprivileged child process to deal with network data */
pmonitor = monitor_init();
/* Store a pointer to the kex for later rekeying */
- pmonitor->m_pkex = &active_state->kex;
+ pmonitor->m_pkex = &ssh->kex;
if (use_privsep == PRIVSEP_ON)
box = ssh_sandbox_init(pmonitor);
pid = fork();
if (pid == -1) {
fatal("fork of unprivileged child failed");
} else if (pid != 0) {
debug2("Network child is on pid %ld", (long)pid);
pmonitor->m_pid = pid;
if (have_agent) {
r = ssh_get_authentication_socket(&auth_sock);
if (r != 0) {
error("Could not get agent socket: %s",
ssh_err(r));
have_agent = 0;
}
}
if (box != NULL)
ssh_sandbox_parent_preauth(box, pid);
- monitor_child_preauth(authctxt, pmonitor);
+ monitor_child_preauth(ssh, pmonitor);
/* Wait for the child's exit status */
while (waitpid(pid, &status, 0) < 0) {
if (errno == EINTR)
continue;
pmonitor->m_pid = -1;
fatal("%s: waitpid: %s", __func__, strerror(errno));
}
privsep_is_preauth = 0;
pmonitor->m_pid = -1;
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0)
fatal("%s: preauth child exited with status %d",
__func__, WEXITSTATUS(status));
} else if (WIFSIGNALED(status))
fatal("%s: preauth child terminated by signal %d",
__func__, WTERMSIG(status));
if (box != NULL)
ssh_sandbox_parent_finish(box);
return 1;
} else {
/* child */
close(pmonitor->m_sendfd);
close(pmonitor->m_log_recvfd);
/* Arrange for logging to be sent to the monitor */
set_log_handler(mm_log_handler, pmonitor);
privsep_preauth_child();
setproctitle("%s", "[net]");
if (box != NULL)
ssh_sandbox_child(box);
return 0;
}
}
static void
-privsep_postauth(Authctxt *authctxt)
+privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
{
#ifdef DISABLE_FD_PASSING
if (1) {
#else
if (authctxt->pw->pw_uid == 0) {
#endif
/* File descriptor passing is broken or root login */
use_privsep = 0;
goto skip;
}
/* New socket pair */
monitor_reinit(pmonitor);
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
fatal("fork of unprivileged child failed");
else if (pmonitor->m_pid != 0) {
verbose("User child is on pid %ld", (long)pmonitor->m_pid);
sshbuf_reset(loginmsg);
- monitor_clear_keystate(pmonitor);
- monitor_child_postauth(pmonitor);
+ monitor_clear_keystate(ssh, pmonitor);
+ monitor_child_postauth(ssh, pmonitor);
/* NEVERREACHED */
exit(0);
}
/* child */
close(pmonitor->m_sendfd);
pmonitor->m_sendfd = -1;
/* Demote the private keys to public keys. */
demote_sensitive_data();
reseed_prngs();
/* Drop privileges */
do_setusercontext(authctxt->pw);
skip:
/* It is safe now to apply the key state */
- monitor_apply_keystate(pmonitor);
+ monitor_apply_keystate(ssh, pmonitor);
/*
* Tell the packet layer that authentication was successful, since
* this information is not part of the key state.
*/
- packet_set_authenticated();
+ ssh_packet_set_authenticated(ssh);
}
static void
append_hostkey_type(struct sshbuf *b, const char *s)
{
int r;
if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
debug3("%s: %s key not permitted by HostkeyAlgorithms",
__func__, s);
return;
}
if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
}
static char *
list_hostkey_types(void)
{
struct sshbuf *b;
struct sshkey *key;
char *ret;
u_int i;
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
for (i = 0; i < options.num_host_key_files; i++) {
key = sensitive_data.host_keys[i];
if (key == NULL)
key = sensitive_data.host_pubkeys[i];
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA:
/* for RSA we also support SHA2 signatures */
append_hostkey_type(b, "rsa-sha2-512");
append_hostkey_type(b, "rsa-sha2-256");
/* FALLTHROUGH */
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
case KEY_XMSS:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
/* If the private key has a cert peer, then list that too */
key = sensitive_data.host_certificates[i];
if (key == NULL)
continue;
switch (key->type) {
case KEY_RSA_CERT:
/* for RSA we also support SHA2 signatures */
append_hostkey_type(b,
"rsa-sha2-512-cert-v01@openssh.com");
append_hostkey_type(b,
"rsa-sha2-256-cert-v01@openssh.com");
/* FALLTHROUGH */
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
case KEY_XMSS_CERT:
append_hostkey_type(b, sshkey_ssh_name(key));
break;
}
}
if ((ret = sshbuf_dup_string(b)) == NULL)
fatal("%s: sshbuf_dup_string failed", __func__);
sshbuf_free(b);
debug("%s: %s", __func__, ret);
return ret;
}
static struct sshkey *
get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh)
{
u_int i;
struct sshkey *key;
for (i = 0; i < options.num_host_key_files; i++) {
switch (type) {
case KEY_RSA_CERT:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_ED25519_CERT:
case KEY_XMSS_CERT:
key = sensitive_data.host_certificates[i];
break;
default:
key = sensitive_data.host_keys[i];
if (key == NULL && !need_private)
key = sensitive_data.host_pubkeys[i];
break;
}
if (key != NULL && key->type == type &&
(key->type != KEY_ECDSA || key->ecdsa_nid == nid))
return need_private ?
sensitive_data.host_keys[i] : key;
}
return NULL;
}
struct sshkey *
get_hostkey_public_by_type(int type, int nid, struct ssh *ssh)
{
return get_hostkey_by_type(type, nid, 0, ssh);
}
struct sshkey *
get_hostkey_private_by_type(int type, int nid, struct ssh *ssh)
{
return get_hostkey_by_type(type, nid, 1, ssh);
}
struct sshkey *
get_hostkey_by_index(int ind)
{
if (ind < 0 || (u_int)ind >= options.num_host_key_files)
return (NULL);
return (sensitive_data.host_keys[ind]);
}
struct sshkey *
get_hostkey_public_by_index(int ind, struct ssh *ssh)
{
if (ind < 0 || (u_int)ind >= options.num_host_key_files)
return (NULL);
return (sensitive_data.host_pubkeys[ind]);
}
int
get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh)
{
u_int i;
for (i = 0; i < options.num_host_key_files; i++) {
if (sshkey_is_cert(key)) {
if (key == sensitive_data.host_certificates[i] ||
(compare && sensitive_data.host_certificates[i] &&
sshkey_equal(key,
sensitive_data.host_certificates[i])))
return (i);
} else {
if (key == sensitive_data.host_keys[i] ||
(compare && sensitive_data.host_keys[i] &&
sshkey_equal(key, sensitive_data.host_keys[i])))
return (i);
if (key == sensitive_data.host_pubkeys[i] ||
(compare && sensitive_data.host_pubkeys[i] &&
sshkey_equal(key, sensitive_data.host_pubkeys[i])))
return (i);
}
}
return (-1);
}
/* Inform the client of all hostkeys */
static void
notify_hostkeys(struct ssh *ssh)
{
struct sshbuf *buf;
struct sshkey *key;
u_int i, nkeys;
int r;
char *fp;
/* Some clients cannot cope with the hostkeys message, skip those. */
- if (datafellows & SSH_BUG_HOSTKEYS)
+ if (ssh->compat & SSH_BUG_HOSTKEYS)
return;
if ((buf = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new", __func__);
for (i = nkeys = 0; i < options.num_host_key_files; i++) {
key = get_hostkey_public_by_index(i, ssh);
if (key == NULL || key->type == KEY_UNSPEC ||
sshkey_is_cert(key))
continue;
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
debug3("%s: key %d: %s %s", __func__, i,
sshkey_ssh_name(key), fp);
free(fp);
if (nkeys == 0) {
- packet_start(SSH2_MSG_GLOBAL_REQUEST);
- packet_put_cstring("hostkeys-00@openssh.com");
- packet_put_char(0); /* want-reply */
+ /*
+ * Start building the request when we find the
+ * first usable key.
+ */
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */
+ sshpkt_fatal(ssh, r, "%s: start request", __func__);
}
+ /* Append the key to the request */
sshbuf_reset(buf);
if ((r = sshkey_putb(key, buf)) != 0)
fatal("%s: couldn't put hostkey %d: %s",
__func__, i, ssh_err(r));
- packet_put_string(sshbuf_ptr(buf), sshbuf_len(buf));
+ if ((r = sshpkt_put_stringb(ssh, buf)) != 0)
+ sshpkt_fatal(ssh, r, "%s: append key", __func__);
nkeys++;
}
debug3("%s: sent %u hostkeys", __func__, nkeys);
if (nkeys == 0)
fatal("%s: no hostkeys", __func__);
- packet_send();
+ if ((r = sshpkt_send(ssh)) != 0)
+ sshpkt_fatal(ssh, r, "%s: send", __func__);
sshbuf_free(buf);
}
/*
* returns 1 if connection should be dropped, 0 otherwise.
* dropping starts at connection #max_startups_begin with a probability
* of (max_startups_rate/100). the probability increases linearly until
* all connections are dropped for startups > max_startups
*/
static int
drop_connection(int startups)
{
int p, r;
if (startups < options.max_startups_begin)
return 0;
if (startups >= options.max_startups)
return 1;
if (options.max_startups_rate == 100)
return 1;
p = 100 - options.max_startups_rate;
p *= startups - options.max_startups_begin;
p /= options.max_startups - options.max_startups_begin;
p += options.max_startups_rate;
r = arc4random_uniform(100);
debug("drop_connection: p %d, r %d", p, r);
return (r < p) ? 1 : 0;
}
static void
usage(void)
{
fprintf(stderr, "%s, %s\n",
SSH_RELEASE,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
fprintf(stderr,
"usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n"
" [-E log_file] [-f config_file] [-g login_grace_time]\n"
" [-h host_key_file] [-o option] [-p port] [-u len]\n"
);
exit(1);
}
static void
send_rexec_state(int fd, struct sshbuf *conf)
{
struct sshbuf *m;
int r;
debug3("%s: entering fd = %d config len %zu", __func__, fd,
sshbuf_len(conf));
/*
* Protocol from reexec master to child:
* string configuration
* string rngseed (only if OpenSSL is not self-seeded)
*/
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if ((r = sshbuf_put_stringb(m, conf)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
rexec_send_rng_seed(m);
#endif
if (ssh_msg_send(fd, 0, m) == -1)
fatal("%s: ssh_msg_send failed", __func__);
sshbuf_free(m);
debug3("%s: done", __func__);
}
static void
recv_rexec_state(int fd, struct sshbuf *conf)
{
struct sshbuf *m;
u_char *cp, ver;
size_t len;
int r;
debug3("%s: entering fd = %d", __func__, fd);
if ((m = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
if (ssh_msg_recv(fd, m) == -1)
fatal("%s: ssh_msg_recv failed", __func__);
if ((r = sshbuf_get_u8(m, &ver)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (ver != 0)
fatal("%s: rexec version mismatch", __func__);
if ((r = sshbuf_get_string(m, &cp, &len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
fatal("%s: buffer error: %s", __func__, ssh_err(r));
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
rexec_recv_rng_seed(m);
#endif
free(cp);
sshbuf_free(m);
debug3("%s: done", __func__);
}
/* Accept a connection from inetd */
static void
server_accept_inetd(int *sock_in, int *sock_out)
{
int fd;
- startup_pipe = -1;
if (rexeced_flag) {
close(REEXEC_CONFIG_PASS_FD);
*sock_in = *sock_out = dup(STDIN_FILENO);
- if (!debug_flag) {
- startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
- close(REEXEC_STARTUP_PIPE_FD);
- }
} else {
*sock_in = dup(STDIN_FILENO);
*sock_out = dup(STDOUT_FILENO);
}
/*
* We intentionally do not close the descriptors 0, 1, and 2
* as our code for setting the descriptors won't work if
* ttyfd happens to be one of those.
*/
if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
if (!log_stderr)
dup2(fd, STDERR_FILENO);
if (fd > (log_stderr ? STDERR_FILENO : STDOUT_FILENO))
close(fd);
}
debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
}
/*
* Listen for TCP connections
*/
static void
listen_on_addrs(struct listenaddr *la)
{
int ret, listen_sock;
struct addrinfo *ai;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
for (ai = la->addrs; ai; ai = ai->ai_next) {
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
continue;
if (num_listen_socks >= MAX_LISTEN_SOCKS)
fatal("Too many listen sockets. "
"Enlarge MAX_LISTEN_SOCKS");
if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
error("getnameinfo failed: %.100s",
ssh_gai_strerror(ret));
continue;
}
/* Create socket for listening. */
listen_sock = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (listen_sock < 0) {
/* kernel may not support ipv6 */
verbose("socket: %.100s", strerror(errno));
continue;
}
if (set_nonblock(listen_sock) == -1) {
close(listen_sock);
continue;
}
if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) == -1) {
verbose("socket: CLOEXEC: %s", strerror(errno));
close(listen_sock);
continue;
}
/* Socket options */
set_reuseaddr(listen_sock);
if (la->rdomain != NULL &&
set_rdomain(listen_sock, la->rdomain) == -1) {
close(listen_sock);
continue;
}
/* Only communicate in IPv6 over AF_INET6 sockets. */
if (ai->ai_family == AF_INET6)
sock_set_v6only(listen_sock);
debug("Bind to port %s on %s.", strport, ntop);
/* Bind the socket to the desired port. */
if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
error("Bind to port %s on %s failed: %.200s.",
strport, ntop, strerror(errno));
close(listen_sock);
continue;
}
listen_socks[num_listen_socks] = listen_sock;
num_listen_socks++;
/* Start listening on the port. */
if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
fatal("listen on [%s]:%s: %.100s",
ntop, strport, strerror(errno));
logit("Server listening on %s port %s%s%s.",
ntop, strport,
la->rdomain == NULL ? "" : " rdomain ",
la->rdomain == NULL ? "" : la->rdomain);
}
}
static void
server_listen(void)
{
u_int i;
for (i = 0; i < options.num_listen_addrs; i++) {
listen_on_addrs(&options.listen_addrs[i]);
freeaddrinfo(options.listen_addrs[i].addrs);
free(options.listen_addrs[i].rdomain);
memset(&options.listen_addrs[i], 0,
sizeof(options.listen_addrs[i]));
}
free(options.listen_addrs);
options.listen_addrs = NULL;
options.num_listen_addrs = 0;
if (!num_listen_socks)
fatal("Cannot bind any address.");
}
/*
* The main TCP accept loop. Note that, for the non-debug case, returns
* from this function are in a forked subprocess.
*/
static void
server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
{
fd_set *fdset;
int i, j, ret, maxfd;
- int startups = 0;
+ int startups = 0, listening = 0, lameduck = 0;
int startup_p[2] = { -1 , -1 };
+ char c = 0;
struct sockaddr_storage from;
socklen_t fromlen;
pid_t pid;
u_char rnd[256];
/* setup fd set for accept */
fdset = NULL;
maxfd = 0;
for (i = 0; i < num_listen_socks; i++)
if (listen_socks[i] > maxfd)
maxfd = listen_socks[i];
/* pipes connected to unauthenticated childs */
startup_pipes = xcalloc(options.max_startups, sizeof(int));
+ startup_flags = xcalloc(options.max_startups, sizeof(int));
for (i = 0; i < options.max_startups; i++)
startup_pipes[i] = -1;
/*
* Stay listening for connections until the system crashes or
* the daemon is killed with a signal.
*/
for (;;) {
- if (received_sighup)
- sighup_restart();
+ if (received_sighup) {
+ if (!lameduck) {
+ debug("Received SIGHUP; waiting for children");
+ close_listen_socks();
+ lameduck = 1;
+ }
+ if (listening <= 0)
+ sighup_restart();
+ }
free(fdset);
fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
sizeof(fd_mask));
for (i = 0; i < num_listen_socks; i++)
FD_SET(listen_socks[i], fdset);
for (i = 0; i < options.max_startups; i++)
if (startup_pipes[i] != -1)
FD_SET(startup_pipes[i], fdset);
/* Wait in select until there is a connection. */
ret = select(maxfd+1, fdset, NULL, NULL, NULL);
if (ret < 0 && errno != EINTR)
error("select: %.100s", strerror(errno));
if (received_sigterm) {
logit("Received signal %d; terminating.",
(int) received_sigterm);
close_listen_socks();
if (options.pid_file != NULL)
unlink(options.pid_file);
exit(received_sigterm == SIGTERM ? 0 : 255);
}
if (ret < 0)
continue;
- for (i = 0; i < options.max_startups; i++)
- if (startup_pipes[i] != -1 &&
- FD_ISSET(startup_pipes[i], fdset)) {
- /*
- * the read end of the pipe is ready
- * if the child has closed the pipe
- * after successful authentication
- * or if the child has died
- */
+ for (i = 0; i < options.max_startups; i++) {
+ if (startup_pipes[i] == -1 ||
+ !FD_ISSET(startup_pipes[i], fdset))
+ continue;
+ switch (read(startup_pipes[i], &c, sizeof(c))) {
+ case -1:
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ if (errno != EPIPE) {
+ error("%s: startup pipe %d (fd=%d): "
+ "read %s", __func__, i,
+ startup_pipes[i], strerror(errno));
+ }
+ /* FALLTHROUGH */
+ case 0:
+ /* child exited or completed auth */
close(startup_pipes[i]);
startup_pipes[i] = -1;
startups--;
+ if (startup_flags[i])
+ listening--;
+ break;
+ case 1:
+ /* child has finished preliminaries */
+ if (startup_flags[i]) {
+ listening--;
+ startup_flags[i] = 0;
+ }
+ break;
}
+ }
for (i = 0; i < num_listen_socks; i++) {
if (!FD_ISSET(listen_socks[i], fdset))
continue;
fromlen = sizeof(from);
*newsock = accept(listen_socks[i],
(struct sockaddr *)&from, &fromlen);
if (*newsock < 0) {
if (errno != EINTR && errno != EWOULDBLOCK &&
errno != ECONNABORTED && errno != EAGAIN)
error("accept: %.100s",
strerror(errno));
if (errno == EMFILE || errno == ENFILE)
usleep(100 * 1000);
continue;
}
if (unset_nonblock(*newsock) == -1) {
close(*newsock);
continue;
}
if (drop_connection(startups) == 1) {
char *laddr = get_local_ipaddr(*newsock);
char *raddr = get_peer_ipaddr(*newsock);
verbose("drop connection #%d from [%s]:%d "
"on [%s]:%d past MaxStartups", startups,
raddr, get_peer_port(*newsock),
laddr, get_local_port(*newsock));
free(laddr);
free(raddr);
close(*newsock);
continue;
}
if (pipe(startup_p) == -1) {
close(*newsock);
continue;
}
if (rexec_flag && socketpair(AF_UNIX,
SOCK_STREAM, 0, config_s) == -1) {
error("reexec socketpair: %s",
strerror(errno));
close(*newsock);
close(startup_p[0]);
close(startup_p[1]);
continue;
}
for (j = 0; j < options.max_startups; j++)
if (startup_pipes[j] == -1) {
startup_pipes[j] = startup_p[0];
if (maxfd < startup_p[0])
maxfd = startup_p[0];
startups++;
+ startup_flags[j] = 1;
break;
}
/*
* Got connection. Fork a child to handle it, unless
* we are in debugging mode.
*/
if (debug_flag) {
/*
* In debugging mode. Close the listening
* socket, and start processing the
* connection without forking.
*/
debug("Server will not fork when running in debugging mode.");
close_listen_socks();
*sock_in = *newsock;
*sock_out = *newsock;
close(startup_p[0]);
close(startup_p[1]);
startup_pipe = -1;
pid = getpid();
if (rexec_flag) {
send_rexec_state(config_s[0], cfg);
close(config_s[0]);
}
- break;
+ return;
}
/*
* Normal production daemon. Fork, and have
* the child process the connection. The
* parent continues listening.
*/
platform_pre_fork();
+ listening++;
if ((pid = fork()) == 0) {
/*
* Child. Close the listening and
* max_startup sockets. Start using
* the accepted socket. Reinitialize
* logging (since our pid has changed).
- * We break out of the loop to handle
+ * We return from this function to handle
* the connection.
*/
platform_post_fork_child();
startup_pipe = startup_p[1];
close_startup_pipes();
close_listen_socks();
*sock_in = *newsock;
*sock_out = *newsock;
log_init(__progname,
options.log_level,
options.log_facility,
log_stderr);
if (rexec_flag)
close(config_s[0]);
- break;
+ else {
+ /*
+ * Signal parent that the preliminaries
+ * for this child are complete. For the
+ * re-exec case, this happens after the
+ * child has received the rexec state
+ * from the server.
+ */
+ (void)atomicio(vwrite, startup_pipe,
+ "\0", 1);
+ }
+ return;
}
/* Parent. Stay in the loop. */
platform_post_fork_parent(pid);
if (pid < 0)
error("fork: %.100s", strerror(errno));
else
debug("Forked child %ld.", (long)pid);
close(startup_p[1]);
if (rexec_flag) {
send_rexec_state(config_s[0], cfg);
close(config_s[0]);
close(config_s[1]);
}
close(*newsock);
/*
* Ensure that our random state differs
* from that of the child
*/
arc4random_stir();
arc4random_buf(rnd, sizeof(rnd));
#ifdef WITH_OPENSSL
RAND_seed(rnd, sizeof(rnd));
if ((RAND_bytes((u_char *)rnd, 1)) != 1)
fatal("%s: RAND_bytes failed", __func__);
#endif
explicit_bzero(rnd, sizeof(rnd));
}
-
- /* child process check (or debug mode) */
- if (num_listen_socks < 0)
- break;
}
}
/*
* If IP options are supported, make sure there are none (log and
* return an error if any are found). Basically we are worried about
* source routing; it can be used to pretend you are somebody
* (ip-address) you are not. That itself may be "almost acceptable"
* under certain circumstances, but rhosts authentication is useless
* if source routing is accepted. Notice also that if we just dropped
* source routing here, the other side could use IP spoofing to do
* rest of the interaction and could still bypass security. So we
* exit here if we detect any IP options.
*/
static void
check_ip_options(struct ssh *ssh)
{
#ifdef IP_OPTIONS
int sock_in = ssh_packet_get_connection_in(ssh);
struct sockaddr_storage from;
u_char opts[200];
socklen_t i, option_size = sizeof(opts), fromlen = sizeof(from);
char text[sizeof(opts) * 3 + 1];
memset(&from, 0, sizeof(from));
if (getpeername(sock_in, (struct sockaddr *)&from,
&fromlen) < 0)
return;
if (from.ss_family != AF_INET)
return;
/* XXX IPv6 options? */
if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
&option_size) >= 0 && option_size != 0) {
text[0] = '\0';
for (i = 0; i < option_size; i++)
snprintf(text + i*3, sizeof(text) - i*3,
" %2.2x", opts[i]);
fatal("Connection from %.100s port %d with IP opts: %.800s",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
}
return;
#endif /* IP_OPTIONS */
}
/* Set the routing domain for this process */
static void
set_process_rdomain(struct ssh *ssh, const char *name)
{
#if defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
if (name == NULL)
return; /* default */
if (strcmp(name, "%D") == 0) {
/* "expands" to routing domain of connection */
if ((name = ssh_packet_rdomain_in(ssh)) == NULL)
return;
}
/* NB. We don't pass 'ssh' to sys_set_process_rdomain() */
return sys_set_process_rdomain(name);
#elif defined(__OpenBSD__)
int rtable, ortable = getrtable();
const char *errstr;
if (name == NULL)
return; /* default */
if (strcmp(name, "%D") == 0) {
/* "expands" to routing domain of connection */
if ((name = ssh_packet_rdomain_in(ssh)) == NULL)
return;
}
rtable = (int)strtonum(name, 0, 255, &errstr);
if (errstr != NULL) /* Shouldn't happen */
fatal("Invalid routing domain \"%s\": %s", name, errstr);
if (rtable != ortable && setrtable(rtable) != 0)
fatal("Unable to set routing domain %d: %s",
rtable, strerror(errno));
debug("%s: set routing domain %d (was %d)", __func__, rtable, ortable);
#else /* defined(__OpenBSD__) */
fatal("Unable to set routing domain: not supported in this platform");
#endif
}
static void
accumulate_host_timing_secret(struct sshbuf *server_cfg,
const struct sshkey *key)
{
static struct ssh_digest_ctx *ctx;
u_char *hash;
size_t len;
struct sshbuf *buf;
int r;
if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL)
fatal("%s: ssh_digest_start", __func__);
if (key == NULL) { /* finalize */
/* add server config in case we are using agent for host keys */
if (ssh_digest_update(ctx, sshbuf_ptr(server_cfg),
sshbuf_len(server_cfg)) != 0)
fatal("%s: ssh_digest_update", __func__);
len = ssh_digest_bytes(SSH_DIGEST_SHA512);
hash = xmalloc(len);
if (ssh_digest_final(ctx, hash, len) != 0)
fatal("%s: ssh_digest_final", __func__);
options.timing_secret = PEEK_U64(hash);
freezero(hash, len);
ssh_digest_free(ctx);
ctx = NULL;
return;
}
if ((buf = sshbuf_new()) == NULL)
fatal("%s could not allocate buffer", __func__);
if ((r = sshkey_private_serialize(key, buf)) != 0)
fatal("sshkey_private_serialize: %s", ssh_err(r));
if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0)
fatal("%s: ssh_digest_update", __func__);
sshbuf_reset(buf);
sshbuf_free(buf);
}
/*
* Main program for the daemon.
*/
int
main(int ac, char **av)
{
struct ssh *ssh = NULL;
extern char *optarg;
extern int optind;
int r, opt, on = 1, already_daemon, remote_port;
int sock_in = -1, sock_out = -1, newsock = -1;
const char *remote_ip, *rdomain;
char *fp, *line, *laddr, *logfile = NULL;
int config_s[2] = { -1 , -1 };
u_int i, j;
u_int64_t ibytes, obytes;
mode_t new_umask;
struct sshkey *key;
struct sshkey *pubkey;
int keytype;
Authctxt *authctxt;
struct connection_info *connection_info = NULL;
ssh_malloc_init(); /* must be called before any mallocs */
#ifdef HAVE_SECUREWARE
(void)set_auth_parameters(ac, av);
#endif
__progname = ssh_get_progname(av[0]);
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
saved_argc = ac;
rexec_argc = ac;
saved_argv = xcalloc(ac + 1, sizeof(*saved_argv));
for (i = 0; (int)i < ac; i++)
saved_argv[i] = xstrdup(av[i]);
saved_argv[i] = NULL;
#ifndef HAVE_SETPROCTITLE
/* Prepare for later setproctitle emulation */
compat_init_setproctitle(ac, av);
av = saved_argv;
#endif
if (geteuid() == 0 && setgroups(0, NULL) == -1)
debug("setgroups(): %.200s", strerror(errno));
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ seed_rng();
+
/* Initialize configuration options to their default values. */
initialize_server_options(&options);
/* Parse command-line arguments. */
while ((opt = getopt(ac, av,
"C:E:b:c:f:g:h:k:o:p:u:46DQRTdeiqrt")) != -1) {
switch (opt) {
case '4':
options.address_family = AF_INET;
break;
case '6':
options.address_family = AF_INET6;
break;
case 'f':
config_file_name = optarg;
break;
case 'c':
servconf_add_hostcert("[command-line]", 0,
&options, optarg);
break;
case 'd':
if (debug_flag == 0) {
debug_flag = 1;
options.log_level = SYSLOG_LEVEL_DEBUG1;
} else if (options.log_level < SYSLOG_LEVEL_DEBUG3)
options.log_level++;
break;
case 'D':
no_daemon_flag = 1;
break;
case 'E':
logfile = optarg;
/* FALLTHROUGH */
case 'e':
log_stderr = 1;
break;
case 'i':
inetd_flag = 1;
break;
case 'r':
rexec_flag = 0;
break;
case 'R':
rexeced_flag = 1;
inetd_flag = 1;
break;
case 'Q':
/* ignored */
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
break;
case 'b':
/* protocol 1, ignored */
break;
case 'p':
options.ports_from_cmdline = 1;
if (options.num_ports >= MAX_PORTS) {
fprintf(stderr, "too many ports.\n");
exit(1);
}
options.ports[options.num_ports++] = a2port(optarg);
if (options.ports[options.num_ports-1] <= 0) {
fprintf(stderr, "Bad port number.\n");
exit(1);
}
break;
case 'g':
if ((options.login_grace_time = convtime(optarg)) == -1) {
fprintf(stderr, "Invalid login grace time.\n");
exit(1);
}
break;
case 'k':
/* protocol 1, ignored */
break;
case 'h':
servconf_add_hostkey("[command-line]", 0,
- &options, optarg);
+ &options, optarg, 1);
break;
case 't':
test_flag = 1;
break;
case 'T':
test_flag = 2;
break;
case 'C':
- connection_info = get_connection_info(0, 0);
+ connection_info = get_connection_info(ssh, 0, 0);
if (parse_server_match_testspec(connection_info,
optarg) == -1)
exit(1);
break;
case 'u':
utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL);
if (utmp_len > HOST_NAME_MAX+1) {
fprintf(stderr, "Invalid utmp length.\n");
exit(1);
}
break;
case 'o':
line = xstrdup(optarg);
if (process_server_config_line(&options, line,
"command-line", 0, NULL, NULL) != 0)
exit(1);
free(line);
break;
case '?':
default:
usage();
break;
}
}
if (rexeced_flag || inetd_flag)
rexec_flag = 0;
- if (!test_flag && (rexec_flag && (av[0] == NULL || *av[0] != '/')))
+ if (!test_flag && rexec_flag && !path_absolute(av[0]))
fatal("sshd re-exec requires execution with an absolute path");
if (rexeced_flag)
closefrom(REEXEC_MIN_FREE_FD);
else
closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
-#ifdef WITH_OPENSSL
- OpenSSL_add_all_algorithms();
-#endif
-
/* If requested, redirect the logs to the specified logfile. */
if (logfile != NULL)
log_redirect_stderr_to(logfile);
/*
* Force logging to stderr until we have loaded the private host
* key (unless started from inetd)
*/
log_init(__progname,
options.log_level == SYSLOG_LEVEL_NOT_SET ?
SYSLOG_LEVEL_INFO : options.log_level,
options.log_facility == SYSLOG_FACILITY_NOT_SET ?
SYSLOG_FACILITY_AUTH : options.log_facility,
log_stderr || !inetd_flag);
/*
* Unset KRB5CCNAME, otherwise the user's session may inherit it from
* root's environment
*/
if (getenv("KRB5CCNAME") != NULL)
(void) unsetenv("KRB5CCNAME");
sensitive_data.have_ssh2_key = 0;
/*
* If we're not doing an extended test do not silently ignore connection
* test params.
*/
if (test_flag < 2 && connection_info != NULL)
fatal("Config test connection parameter (-C) provided without "
"test mode (-T)");
/* Fetch our configuration */
if ((cfg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
- if (rexeced_flag)
+ if (rexeced_flag) {
recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg);
+ if (!debug_flag) {
+ startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
+ close(REEXEC_STARTUP_PIPE_FD);
+ /*
+ * Signal parent that this child is at a point where
+ * they can go away if they have a SIGHUP pending.
+ */
+ (void)atomicio(vwrite, startup_pipe, "\0", 1);
+ }
+ }
else if (strcasecmp(config_file_name, "none") != 0)
load_server_config(config_file_name, cfg);
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
cfg, NULL);
- seed_rng();
-
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
/* challenge-response is implemented via keyboard interactive */
if (options.challenge_response_authentication)
options.kbd_interactive_authentication = 1;
/* Check that options are sensible */
if (options.authorized_keys_command_user == NULL &&
(options.authorized_keys_command != NULL &&
strcasecmp(options.authorized_keys_command, "none") != 0))
fatal("AuthorizedKeysCommand set without "
"AuthorizedKeysCommandUser");
if (options.authorized_principals_command_user == NULL &&
(options.authorized_principals_command != NULL &&
strcasecmp(options.authorized_principals_command, "none") != 0))
fatal("AuthorizedPrincipalsCommand set without "
"AuthorizedPrincipalsCommandUser");
/*
* Check whether there is any path through configured auth methods.
* Unfortunately it is not possible to verify this generally before
* daemonisation in the presence of Match block, but this catches
* and warns for trivial misconfigurations that could break login.
*/
if (options.num_auth_methods != 0) {
for (i = 0; i < options.num_auth_methods; i++) {
if (auth2_methods_valid(options.auth_methods[i],
1) == 0)
break;
}
if (i >= options.num_auth_methods)
fatal("AuthenticationMethods cannot be satisfied by "
"enabled authentication methods");
}
/* Check that there are no remaining arguments. */
if (optind < ac) {
fprintf(stderr, "Extra argument %s.\n", av[optind]);
exit(1);
}
debug("sshd version %s, %s", SSH_VERSION,
#ifdef WITH_OPENSSL
- SSLeay_version(SSLEAY_VERSION)
+ OpenSSL_version(OPENSSL_VERSION)
#else
"without OpenSSL"
#endif
);
/* Store privilege separation user for later use if required. */
privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0);
if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
if (privsep_chroot || options.kerberos_authentication)
fatal("Privilege separation user %s does not exist",
SSH_PRIVSEP_USER);
} else {
privsep_pw = pwcopy(privsep_pw);
freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd));
privsep_pw->pw_passwd = xstrdup("*");
}
endpwent();
/* load host keys */
sensitive_data.host_keys = xcalloc(options.num_host_key_files,
sizeof(struct sshkey *));
sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files,
sizeof(struct sshkey *));
if (options.host_key_agent) {
if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME))
setenv(SSH_AUTHSOCKET_ENV_NAME,
options.host_key_agent, 1);
if ((r = ssh_get_authentication_socket(NULL)) == 0)
have_agent = 1;
else
error("Could not connect to agent \"%s\": %s",
options.host_key_agent, ssh_err(r));
}
for (i = 0; i < options.num_host_key_files; i++) {
+ int ll = options.host_key_file_userprovided[i] ?
+ SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1;
+
if (options.host_key_files[i] == NULL)
continue;
if ((r = sshkey_load_private(options.host_key_files[i], "",
&key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
- error("Error loading host key \"%s\": %s",
+ do_log2(ll, "Unable to load host key \"%s\": %s",
options.host_key_files[i], ssh_err(r));
if ((r = sshkey_load_public(options.host_key_files[i],
&pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
- error("Error loading host key \"%s\": %s",
+ do_log2(ll, "Unable to load host key \"%s\": %s",
options.host_key_files[i], ssh_err(r));
if (pubkey == NULL && key != NULL)
if ((r = sshkey_from_private(key, &pubkey)) != 0)
fatal("Could not demote key: \"%s\": %s",
options.host_key_files[i], ssh_err(r));
sensitive_data.host_keys[i] = key;
sensitive_data.host_pubkeys[i] = pubkey;
if (key == NULL && pubkey != NULL && have_agent) {
debug("will rely on agent for hostkey %s",
options.host_key_files[i]);
keytype = pubkey->type;
} else if (key != NULL) {
keytype = key->type;
accumulate_host_timing_secret(cfg, key);
} else {
- error("Could not load host key: %s",
+ do_log2(ll, "Unable to load host key: %s",
options.host_key_files[i]);
sensitive_data.host_keys[i] = NULL;
sensitive_data.host_pubkeys[i] = NULL;
continue;
}
switch (keytype) {
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
case KEY_XMSS:
if (have_agent || key != NULL)
sensitive_data.have_ssh2_key = 1;
break;
}
if ((fp = sshkey_fingerprint(pubkey, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
fatal("sshkey_fingerprint failed");
debug("%s host key #%d: %s %s",
key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp);
free(fp);
}
accumulate_host_timing_secret(cfg, NULL);
if (!sensitive_data.have_ssh2_key) {
logit("sshd: no hostkeys available -- exiting.");
exit(1);
}
/*
* Load certificates. They are stored in an array at identical
* indices to the public keys that they relate to.
*/
sensitive_data.host_certificates = xcalloc(options.num_host_key_files,
sizeof(struct sshkey *));
for (i = 0; i < options.num_host_key_files; i++)
sensitive_data.host_certificates[i] = NULL;
for (i = 0; i < options.num_host_cert_files; i++) {
if (options.host_cert_files[i] == NULL)
continue;
if ((r = sshkey_load_public(options.host_cert_files[i],
&key, NULL)) != 0) {
error("Could not load host certificate \"%s\": %s",
options.host_cert_files[i], ssh_err(r));
continue;
}
if (!sshkey_is_cert(key)) {
error("Certificate file is not a certificate: %s",
options.host_cert_files[i]);
sshkey_free(key);
continue;
}
/* Find matching private key */
for (j = 0; j < options.num_host_key_files; j++) {
if (sshkey_equal_public(key,
sensitive_data.host_keys[j])) {
sensitive_data.host_certificates[j] = key;
break;
}
}
if (j >= options.num_host_key_files) {
error("No matching private key for certificate: %s",
options.host_cert_files[i]);
sshkey_free(key);
continue;
}
sensitive_data.host_certificates[j] = key;
debug("host certificate: #%u type %d %s", j, key->type,
sshkey_type(key));
}
if (privsep_chroot) {
struct stat st;
if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
(S_ISDIR(st.st_mode) == 0))
fatal("Missing privilege separation directory: %s",
_PATH_PRIVSEP_CHROOT_DIR);
#ifdef HAVE_CYGWIN
if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
(st.st_uid != getuid () ||
(st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
#else
if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
#endif
fatal("%s must be owned by root and not group or "
"world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
}
if (test_flag > 1) {
/*
* If no connection info was provided by -C then use
* use a blank one that will cause no predicate to match.
*/
if (connection_info == NULL)
- connection_info = get_connection_info(0, 0);
+ connection_info = get_connection_info(ssh, 0, 0);
parse_server_match_config(&options, connection_info);
dump_config(&options);
}
/* Configuration looks good, so exit if in test mode. */
if (test_flag)
exit(0);
/*
* Clear out any supplemental groups we may have inherited. This
* prevents inadvertent creation of files with bad modes (in the
* portable version at least, it's certainly possible for PAM
* to create a file, and we can't control the code in every
* module which might be used).
*/
if (setgroups(0, NULL) < 0)
debug("setgroups() failed: %.200s", strerror(errno));
if (rexec_flag) {
if (rexec_argc < 0)
fatal("rexec_argc %d < 0", rexec_argc);
rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *));
for (i = 0; i < (u_int)rexec_argc; i++) {
debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
rexec_argv[i] = saved_argv[i];
}
rexec_argv[rexec_argc] = "-R";
rexec_argv[rexec_argc + 1] = NULL;
}
/* Ensure that umask disallows at least group and world write */
new_umask = umask(0077) | 0022;
(void) umask(new_umask);
/* Initialize the log (it is reinitialized below in case we forked). */
if (debug_flag && (!inetd_flag || rexeced_flag))
log_stderr = 1;
log_init(__progname, options.log_level, options.log_facility, log_stderr);
/*
* If not in debugging mode, not started from inetd and not already
* daemonized (eg re-exec via SIGHUP), disconnect from the controlling
* terminal, and fork. The original process exits.
*/
already_daemon = daemonized();
if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) {
if (daemon(0, 0) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
disconnect_controlling_tty();
}
/* Reinitialize the log (because of the fork above). */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
/* Chdir to the root directory so that the current disk can be
unmounted if desired. */
if (chdir("/") == -1)
error("chdir(\"/\"): %s", strerror(errno));
/* ignore SIGPIPE */
signal(SIGPIPE, SIG_IGN);
/* Get a connection, either from inetd or a listening TCP socket */
if (inetd_flag) {
server_accept_inetd(&sock_in, &sock_out);
} else {
platform_pre_listen();
server_listen();
signal(SIGHUP, sighup_handler);
signal(SIGCHLD, main_sigchld_handler);
signal(SIGTERM, sigterm_handler);
signal(SIGQUIT, sigterm_handler);
/*
* Write out the pid file after the sigterm handler
* is setup and the listen sockets are bound
*/
if (options.pid_file != NULL && !debug_flag) {
FILE *f = fopen(options.pid_file, "w");
if (f == NULL) {
error("Couldn't create pid file \"%s\": %s",
options.pid_file, strerror(errno));
} else {
fprintf(f, "%ld\n", (long) getpid());
fclose(f);
}
}
/* Accept a connection and return in a forked child */
server_accept_loop(&sock_in, &sock_out,
&newsock, config_s);
}
/* This is the child processing a new connection. */
setproctitle("%s", "[accepted]");
/*
* Create a new session and process group since the 4.4BSD
* setlogin() affects the entire process group. We don't
* want the child to be able to affect the parent.
*/
#if !defined(SSHD_ACQUIRES_CTTY)
/*
* If setsid is called, on some platforms sshd will later acquire a
* controlling terminal which will result in "could not set
* controlling tty" errors.
*/
if (!debug_flag && !inetd_flag && setsid() < 0)
error("setsid: %.100s", strerror(errno));
#endif
if (rexec_flag) {
int fd;
debug("rexec start in %d out %d newsock %d pipe %d sock %d",
sock_in, sock_out, newsock, startup_pipe, config_s[0]);
dup2(newsock, STDIN_FILENO);
dup2(STDIN_FILENO, STDOUT_FILENO);
if (startup_pipe == -1)
close(REEXEC_STARTUP_PIPE_FD);
else if (startup_pipe != REEXEC_STARTUP_PIPE_FD) {
dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD);
close(startup_pipe);
startup_pipe = REEXEC_STARTUP_PIPE_FD;
}
dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
close(config_s[1]);
execv(rexec_argv[0], rexec_argv);
/* Reexec has failed, fall back and continue */
error("rexec of %s failed: %s", rexec_argv[0], strerror(errno));
recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL);
log_init(__progname, options.log_level,
options.log_facility, log_stderr);
/* Clean up fds */
close(REEXEC_CONFIG_PASS_FD);
newsock = sock_out = sock_in = dup(STDIN_FILENO);
if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
if (fd > STDERR_FILENO)
close(fd);
}
debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
sock_in, sock_out, newsock, startup_pipe, config_s[0]);
}
/* Executed child processes don't need these. */
fcntl(sock_out, F_SETFD, FD_CLOEXEC);
fcntl(sock_in, F_SETFD, FD_CLOEXEC);
/*
* Disable the key regeneration alarm. We will not regenerate the
* key since we are no longer in a position to give it to anyone. We
* will not restart on SIGHUP since it no longer makes sense.
*/
alarm(0);
signal(SIGALRM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
signal(SIGINT, SIG_DFL);
/*
* Register our connection. This turns encryption off because we do
* not have a key.
*/
- packet_set_connection(sock_in, sock_out);
- packet_set_server();
- ssh = active_state; /* XXX */
+ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL)
+ fatal("Unable to create connection");
+ the_active_state = ssh;
+ ssh_packet_set_server(ssh);
check_ip_options(ssh);
/* Prepare the channels layer */
channel_init_channels(ssh);
channel_set_af(ssh, options.address_family);
process_permitopen(ssh, &options);
/* Set SO_KEEPALIVE if requested. */
- if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
+ if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) &&
setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
if ((remote_port = ssh_remote_port(ssh)) < 0) {
debug("ssh_remote_port failed");
cleanup_exit(255);
}
if (options.routing_domain != NULL)
set_process_rdomain(ssh, options.routing_domain);
/*
* The rest of the code depends on the fact that
* ssh_remote_ipaddr() caches the remote ip, even if
* the socket goes away.
*/
remote_ip = ssh_remote_ipaddr(ssh);
#ifdef SSH_AUDIT_EVENTS
audit_connection_from(remote_ip, remote_port);
#endif
rdomain = ssh_packet_rdomain_in(ssh);
/* Log the connection. */
laddr = get_local_ipaddr(sock_in);
verbose("Connection from %s port %d on %s port %d%s%s%s",
remote_ip, remote_port, laddr, ssh_local_port(ssh),
rdomain == NULL ? "" : " rdomain \"",
rdomain == NULL ? "" : rdomain,
rdomain == NULL ? "" : "\"");
free(laddr);
/*
* We don't want to listen forever unless the other side
* successfully authenticates itself. So we set up an alarm which is
* cleared after successful authentication. A limit of zero
* indicates no limit. Note that we don't set the alarm in debugging
* mode; it is just annoying to have the server exit just when you
* are about to discover the bug.
*/
signal(SIGALRM, grace_alarm_handler);
if (!debug_flag)
alarm(options.login_grace_time);
- sshd_exchange_identification(ssh, sock_in, sock_out);
- packet_set_nonblocking();
+ if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0)
+ cleanup_exit(255); /* error already logged */
+
+ ssh_packet_set_nonblocking(ssh);
/* allocate authentication context */
authctxt = xcalloc(1, sizeof(*authctxt));
+ ssh->authctxt = authctxt;
authctxt->loginmsg = loginmsg;
/* XXX global for cleanup, access from other modules */
the_authctxt = authctxt;
/* Set default key authentication options */
if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL)
fatal("allocation failed");
/* prepare buffer to collect messages to display to user after login */
if ((loginmsg = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __func__);
auth_debug_reset();
if (use_privsep) {
- if (privsep_preauth(authctxt) == 1)
+ if (privsep_preauth(ssh) == 1)
goto authenticated;
} else if (have_agent) {
if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
error("Unable to get agent socket: %s", ssh_err(r));
have_agent = 0;
}
}
/* perform the key exchange */
/* authenticate user and start session */
- do_ssh2_kex();
- do_authentication2(authctxt);
+ do_ssh2_kex(ssh);
+ do_authentication2(ssh);
/*
* If we use privilege separation, the unprivileged child transfers
* the current keystate and exits
*/
if (use_privsep) {
- mm_send_keystate(pmonitor);
- packet_clear_keys();
+ mm_send_keystate(ssh, pmonitor);
+ ssh_packet_clear_keys(ssh);
exit(0);
}
authenticated:
/*
* Cancel the alarm we set to limit the time taken for
* authentication.
*/
alarm(0);
signal(SIGALRM, SIG_DFL);
authctxt->authenticated = 1;
if (startup_pipe != -1) {
close(startup_pipe);
startup_pipe = -1;
}
#ifdef SSH_AUDIT_EVENTS
- audit_event(SSH_AUTH_SUCCESS);
+ audit_event(ssh, SSH_AUTH_SUCCESS);
#endif
#ifdef GSSAPI
if (options.gss_authentication) {
temporarily_use_uid(authctxt->pw);
ssh_gssapi_storecreds();
restore_uid();
}
#endif
#ifdef USE_PAM
if (options.use_pam) {
do_pam_setcred(1);
do_pam_session(ssh);
}
#endif
/*
* In privilege separation, we fork another child and prepare
* file descriptor passing.
*/
if (use_privsep) {
- privsep_postauth(authctxt);
+ privsep_postauth(ssh, authctxt);
/* the monitor process [priv] will not return */
}
- packet_set_timeout(options.client_alive_interval,
+ ssh_packet_set_timeout(ssh, options.client_alive_interval,
options.client_alive_count_max);
/* Try to send all our hostkeys to the client */
notify_hostkeys(ssh);
/* Start session. */
do_authenticated(ssh, authctxt);
/* The connection has been terminated. */
- packet_get_bytes(&ibytes, &obytes);
+ ssh_packet_get_bytes(ssh, &ibytes, &obytes);
verbose("Transferred: sent %llu, received %llu bytes",
(unsigned long long)obytes, (unsigned long long)ibytes);
verbose("Closing connection to %.500s port %d", remote_ip, remote_port);
#ifdef USE_PAM
if (options.use_pam)
finish_pam();
#endif /* USE_PAM */
#ifdef SSH_AUDIT_EVENTS
- PRIVSEP(audit_event(SSH_CONNECTION_CLOSE));
+ PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE));
#endif
- packet_close();
+ ssh_packet_close(ssh);
if (use_privsep)
mm_terminate();
exit(0);
}
int
-sshd_hostkey_sign(struct sshkey *privkey, struct sshkey *pubkey,
- u_char **signature, size_t *slenp, const u_char *data, size_t dlen,
- const char *alg, u_int flag)
+sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
+ struct sshkey *pubkey, u_char **signature, size_t *slenp,
+ const u_char *data, size_t dlen, const char *alg)
{
int r;
- if (privkey) {
- if (PRIVSEP(sshkey_sign(privkey, signature, slenp, data, dlen,
- alg, datafellows)) < 0)
- fatal("%s: key_sign failed", __func__);
- } else if (use_privsep) {
- if (mm_sshkey_sign(pubkey, signature, slenp, data, dlen,
- alg, datafellows) < 0)
- fatal("%s: pubkey_sign failed", __func__);
+ if (use_privsep) {
+ if (privkey) {
+ if (mm_sshkey_sign(ssh, privkey, signature, slenp,
+ data, dlen, alg, ssh->compat) < 0)
+ fatal("%s: privkey sign failed", __func__);
+ } else {
+ if (mm_sshkey_sign(ssh, pubkey, signature, slenp,
+ data, dlen, alg, ssh->compat) < 0)
+ fatal("%s: pubkey sign failed", __func__);
+ }
} else {
- if ((r = ssh_agent_sign(auth_sock, pubkey, signature, slenp,
- data, dlen, alg, datafellows)) != 0)
- fatal("%s: ssh_agent_sign failed: %s",
- __func__, ssh_err(r));
+ if (privkey) {
+ if (sshkey_sign(privkey, signature, slenp, data, dlen,
+ alg, ssh->compat) < 0)
+ fatal("%s: privkey sign failed", __func__);
+ } else {
+ if ((r = ssh_agent_sign(auth_sock, pubkey,
+ signature, slenp, data, dlen, alg,
+ ssh->compat)) != 0) {
+ fatal("%s: agent sign failed: %s",
+ __func__, ssh_err(r));
+ }
+ }
}
return 0;
}
/* SSH2 key exchange */
static void
-do_ssh2_kex(void)
+do_ssh2_kex(struct ssh *ssh)
{
char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
struct kex *kex;
int r;
myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
options.kex_algorithms);
myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(
options.ciphers);
myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(
options.ciphers);
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
if (options.compression == COMP_NONE) {
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
}
if (options.rekey_limit || options.rekey_interval)
- packet_set_rekey_limits(options.rekey_limit,
+ ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
options.rekey_interval);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
list_hostkey_types());
/* 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));
- kex = active_state->kex;
+ kex = ssh->kex;
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
- kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
- kex->kex[KEX_DH_GRP14_SHA256] = kexdh_server;
- kex->kex[KEX_DH_GRP16_SHA512] = kexdh_server;
- kex->kex[KEX_DH_GRP18_SHA512] = kexdh_server;
+ kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+ kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif
- 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->kex[KEX_C25519_SHA256] = kex_gen_server;
+ kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
kex->sign = sshd_hostkey_sign;
- ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);
+ ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done);
session_id2 = kex->session_id;
session_id2_len = kex->session_id_len;
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
packet_start(SSH2_MSG_IGNORE);
packet_put_cstring("markus");
packet_send();
packet_write_wait();
#endif
debug("KEX done");
}
/* server specific fatal cleanup */
void
cleanup_exit(int i)
{
- struct ssh *ssh = active_state; /* XXX */
-
- if (the_authctxt) {
- do_cleanup(ssh, the_authctxt);
+ if (the_active_state != NULL && the_authctxt != NULL) {
+ do_cleanup(the_active_state, the_authctxt);
if (use_privsep && privsep_is_preauth &&
pmonitor != NULL && pmonitor->m_pid > 1) {
debug("Killing privsep child %d", pmonitor->m_pid);
if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
errno != ESRCH)
error("%s: kill(%d): %s", __func__,
pmonitor->m_pid, strerror(errno));
}
}
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
- if (!use_privsep || mm_is_monitor())
- audit_event(SSH_CONNECTION_ABANDON);
+ if (the_active_state != NULL && (!use_privsep || mm_is_monitor()))
+ audit_event(the_active_state, SSH_CONNECTION_ABANDON);
#endif
_exit(i);
}
diff --git a/sshd_config.0 b/sshd_config.0
index af54da6b2220..545b9a89c039 100644
--- a/sshd_config.0
+++ b/sshd_config.0
@@ -1,1092 +1,1092 @@
SSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5)
NAME
sshd_config M-bM-^@M-^S OpenSSH SSH daemon configuration file
DESCRIPTION
sshd(8) reads configuration data from /etc/ssh/sshd_config (or the file
specified with -f on the command line). The file contains keyword-
argument pairs, one per line. For each keyword, the first obtained value
will be used. Lines starting with M-bM-^@M-^X#M-bM-^@M-^Y and empty lines are interpreted as
comments. Arguments may optionally be enclosed in double quotes (") in
order to represent arguments containing spaces.
The possible keywords and their meanings are as follows (note that
keywords are case-insensitive and arguments are case-sensitive):
AcceptEnv
Specifies what environment variables sent by the client will be
copied into the session's environ(7). See SendEnv and SetEnv in
ssh_config(5) for how to configure the client. The TERM
environment variable is always accepted whenever the client
requests a pseudo-terminal as it is required by the protocol.
Variables are specified by name, which may contain the wildcard
characters M-bM-^@M-^X*M-bM-^@M-^Y and M-bM-^@M-^X?M-bM-^@M-^Y. Multiple environment variables may be
separated by whitespace or spread across multiple AcceptEnv
directives. Be warned that some environment variables could be
used to bypass restricted user environments. For this reason,
care should be taken in the use of this directive. The default
is not to accept any environment variables.
AddressFamily
Specifies which address family should be used by sshd(8). Valid
arguments are any (the default), inet (use IPv4 only), or inet6
(use IPv6 only).
AllowAgentForwarding
Specifies whether ssh-agent(1) forwarding is permitted. The
default is yes. Note that disabling agent forwarding does not
improve security unless users are also denied shell access, as
they can always install their own forwarders.
AllowGroups
This keyword can be followed by a list of group name patterns,
separated by spaces. If specified, login is allowed only for
users whose primary group or supplementary group list matches one
of the patterns. Only group names are valid; a numerical group
ID is not recognized. By default, login is allowed for all
groups. The allow/deny directives are processed in the following
order: DenyUsers, AllowUsers, DenyGroups, and finally
AllowGroups.
See PATTERNS in ssh_config(5) for more information on patterns.
AllowStreamLocalForwarding
Specifies whether StreamLocal (Unix-domain socket) forwarding is
permitted. The available options are yes (the default) or all to
allow StreamLocal forwarding, no to prevent all StreamLocal
forwarding, local to allow local (from the perspective of ssh(1))
forwarding only or remote to allow remote forwarding only. Note
that disabling StreamLocal forwarding does not improve security
unless users are also denied shell access, as they can always
install their own forwarders.
AllowTcpForwarding
Specifies whether TCP forwarding is permitted. The available
options are yes (the default) or all to allow TCP forwarding, no
to prevent all TCP forwarding, local to allow local (from the
perspective of ssh(1)) forwarding only or remote to allow remote
forwarding only. Note that disabling TCP forwarding does not
improve security unless users are also denied shell access, as
they can always install their own forwarders.
AllowUsers
This keyword can be followed by a list of user name patterns,
separated by spaces. If specified, login is allowed only for
user names that match one of the patterns. Only user names are
valid; a numerical user ID is not recognized. By default, login
is allowed for all users. If the pattern takes the form
USER@HOST then USER and HOST are separately checked, restricting
logins to particular users from particular hosts. HOST criteria
may additionally contain addresses to match in CIDR
address/masklen format. The allow/deny directives are processed
in the following order: DenyUsers, AllowUsers, DenyGroups, and
finally AllowGroups.
See PATTERNS in ssh_config(5) for more information on patterns.
AuthenticationMethods
Specifies the authentication methods that must be successfully
completed for a user to be granted access. This option must be
followed by one or more lists of comma-separated authentication
method names, or by the single string any to indicate the default
behaviour of accepting any single authentication method. If the
default is overridden, then successful authentication requires
completion of every method in at least one of these lists.
For example, "publickey,password publickey,keyboard-interactive"
would require the user to complete public key authentication,
followed by either password or keyboard interactive
authentication. Only methods that are next in one or more lists
are offered at each stage, so for this example it would not be
possible to attempt password or keyboard-interactive
authentication before public key.
For keyboard interactive authentication it is also possible to
restrict authentication to a specific device by appending a colon
followed by the device identifier bsdauth or pam. depending on
the server configuration. For example,
"keyboard-interactive:bsdauth" would restrict keyboard
interactive authentication to the bsdauth device.
If the publickey method is listed more than once, sshd(8)
verifies that keys that have been used successfully are not
reused for subsequent authentications. For example,
"publickey,publickey" requires successful authentication using
two different public keys.
Note that each authentication method listed should also be
explicitly enabled in the configuration.
The available authentication methods are: "gssapi-with-mic",
"hostbased", "keyboard-interactive", "none" (used for access to
password-less accounts when PermitEmptyPasswords is enabled),
"password" and "publickey".
AuthorizedKeysCommand
Specifies a program to be used to look up the user's public keys.
The program must be owned by root, not writable by group or
others and specified by an absolute path. Arguments to
AuthorizedKeysCommand accept the tokens described in the TOKENS
section. If no arguments are specified then the username of the
target user is used.
The program should produce on standard output zero or more lines
of authorized_keys output (see AUTHORIZED_KEYS in sshd(8)). If a
key supplied by AuthorizedKeysCommand does not successfully
authenticate and authorize the user then public key
authentication continues using the usual AuthorizedKeysFile
files. By default, no AuthorizedKeysCommand is run.
AuthorizedKeysCommandUser
Specifies the user under whose account the AuthorizedKeysCommand
is run. It is recommended to use a dedicated user that has no
other role on the host than running authorized keys commands. If
AuthorizedKeysCommand is specified but AuthorizedKeysCommandUser
is not, then sshd(8) will refuse to start.
AuthorizedKeysFile
Specifies the file that contains the public keys used for user
authentication. The format is described in the AUTHORIZED_KEYS
FILE FORMAT section of sshd(8). Arguments to AuthorizedKeysFile
accept the tokens described in the TOKENS section. After
expansion, AuthorizedKeysFile is taken to be an absolute path or
one relative to the user's home directory. Multiple files may be
listed, separated by whitespace. Alternately this option may be
set to none to skip checking for user keys in files. The default
is ".ssh/authorized_keys .ssh/authorized_keys2".
AuthorizedPrincipalsCommand
Specifies a program to be used to generate the list of allowed
certificate principals as per AuthorizedPrincipalsFile. The
program must be owned by root, not writable by group or others
and specified by an absolute path. Arguments to
AuthorizedPrincipalsCommand accept the tokens described in the
TOKENS section. If no arguments are specified then the username
of the target user is used.
The program should produce on standard output zero or more lines
of AuthorizedPrincipalsFile output. If either
AuthorizedPrincipalsCommand or AuthorizedPrincipalsFile is
specified, then certificates offered by the client for
authentication must contain a principal that is listed. By
default, no AuthorizedPrincipalsCommand is run.
AuthorizedPrincipalsCommandUser
Specifies the user under whose account the
AuthorizedPrincipalsCommand is run. It is recommended to use a
dedicated user that has no other role on the host than running
authorized principals commands. If AuthorizedPrincipalsCommand
is specified but AuthorizedPrincipalsCommandUser is not, then
sshd(8) will refuse to start.
AuthorizedPrincipalsFile
Specifies a file that lists principal names that are accepted for
certificate authentication. When using certificates signed by a
key listed in TrustedUserCAKeys, this file lists names, one of
which must appear in the certificate for it to be accepted for
authentication. Names are listed one per line preceded by key
options (as described in AUTHORIZED_KEYS FILE FORMAT in sshd(8)).
Empty lines and comments starting with M-bM-^@M-^X#M-bM-^@M-^Y are ignored.
Arguments to AuthorizedPrincipalsFile accept the tokens described
in the TOKENS section. After expansion, AuthorizedPrincipalsFile
is taken to be an absolute path or one relative to the user's
home directory. The default is none, i.e. not to use a
principals file M-bM-^@M-^S in this case, the username of the user must
appear in a certificate's principals list for it to be accepted.
Note that AuthorizedPrincipalsFile is only used when
authentication proceeds using a CA listed in TrustedUserCAKeys
and is not consulted for certification authorities trusted via
~/.ssh/authorized_keys, though the principals= key option offers
a similar facility (see sshd(8) for details).
Banner The contents of the specified file are sent to the remote user
before authentication is allowed. If the argument is none then
no banner is displayed. By default, no banner is displayed.
CASignatureAlgorithms
Specifies which algorithms are allowed for signing of
certificates by certificate authorities (CAs). The default is:
ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
Certificates signed using other algorithms will not be accepted
for public key or host-based authentication.
ChallengeResponseAuthentication
Specifies whether challenge-response authentication is allowed
(e.g. via PAM or through authentication styles supported in
login.conf(5)) The default is yes.
ChrootDirectory
Specifies the pathname of a directory to chroot(2) to after
authentication. At session startup sshd(8) checks that all
components of the pathname are root-owned directories which are
not writable by any other user or group. After the chroot,
sshd(8) changes the working directory to the user's home
directory. Arguments to ChrootDirectory accept the tokens
described in the TOKENS section.
The ChrootDirectory must contain the necessary files and
directories to support the user's session. For an interactive
session this requires at least a shell, typically sh(1), and
basic /dev nodes such as null(4), zero(4), stdin(4), stdout(4),
stderr(4), and tty(4) devices. For file transfer sessions using
SFTP no additional configuration of the environment is necessary
if the in-process sftp-server is used, though sessions which use
logging may require /dev/log inside the chroot directory on some
operating systems (see sftp-server(8) for details).
For safety, it is very important that the directory hierarchy be
prevented from modification by other processes on the system
(especially those outside the jail). Misconfiguration can lead
to unsafe environments which sshd(8) cannot detect.
The default is none, indicating not to chroot(2).
Ciphers
Specifies the ciphers allowed. Multiple ciphers must be comma-
separated. If the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character,
then the specified ciphers will be appended to the default set
instead of replacing them. If the specified value begins with a
M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified ciphers (including wildcards)
will be removed from the default set instead of replacing them.
The supported ciphers are:
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
aes128-ctr
aes192-ctr
aes256-ctr
aes128-gcm@openssh.com
aes256-gcm@openssh.com
chacha20-poly1305@openssh.com
The default is:
chacha20-poly1305@openssh.com,
aes128-ctr,aes192-ctr,aes256-ctr,
aes128-gcm@openssh.com,aes256-gcm@openssh.com
The list of available ciphers may also be obtained using "ssh -Q
cipher".
ClientAliveCountMax
Sets the number of client alive messages which may be sent
without sshd(8) receiving any messages back from the client. If
this threshold is reached while client alive messages are being
sent, sshd will disconnect the client, terminating the session.
It is important to note that the use of client alive messages is
very different from TCPKeepAlive. The client alive messages are
sent through the encrypted channel and therefore will not be
spoofable. The TCP keepalive option enabled by TCPKeepAlive is
spoofable. The client alive mechanism is valuable when the
client or server depend on knowing when a connection has become
inactive.
The default value is 3. If ClientAliveInterval is set to 15, and
ClientAliveCountMax is left at the default, unresponsive SSH
clients will be disconnected after approximately 45 seconds.
ClientAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the client, sshd(8) will send a message
through the encrypted channel to request a response from the
client. The default is 0, indicating that these messages will
not be sent to the client.
Compression
Specifies whether compression is enabled after the user has
authenticated successfully. The argument must be yes, delayed (a
legacy synonym for yes) or no. The default is yes.
DenyGroups
This keyword can be followed by a list of group name patterns,
separated by spaces. Login is disallowed for users whose primary
group or supplementary group list matches one of the patterns.
Only group names are valid; a numerical group ID is not
recognized. By default, login is allowed for all groups. The
allow/deny directives are processed in the following order:
DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups.
See PATTERNS in ssh_config(5) for more information on patterns.
DenyUsers
This keyword can be followed by a list of user name patterns,
separated by spaces. Login is disallowed for user names that
match one of the patterns. Only user names are valid; a
numerical user ID is not recognized. By default, login is
allowed for all users. If the pattern takes the form USER@HOST
then USER and HOST are separately checked, restricting logins to
particular users from particular hosts. HOST criteria may
additionally contain addresses to match in CIDR address/masklen
format. The allow/deny directives are processed in the following
order: DenyUsers, AllowUsers, DenyGroups, and finally
AllowGroups.
See PATTERNS in ssh_config(5) for more information on patterns.
DisableForwarding
Disables all forwarding features, including X11, ssh-agent(1),
TCP and StreamLocal. This option overrides all other forwarding-
related options and may simplify restricted configurations.
ExposeAuthInfo
Writes a temporary file containing a list of authentication
methods and public credentials (e.g. keys) used to authenticate
the user. The location of the file is exposed to the user
session through the SSH_USER_AUTH environment variable. The
default is no.
FingerprintHash
Specifies the hash algorithm used when logging key fingerprints.
Valid options are: md5 and sha256. The default is sha256.
ForceCommand
Forces the execution of the command specified by ForceCommand,
ignoring any command supplied by the client and ~/.ssh/rc if
present. The command is invoked by using the user's login shell
with the -c option. This applies to shell, command, or subsystem
execution. It is most useful inside a Match block. The command
originally supplied by the client is available in the
SSH_ORIGINAL_COMMAND environment variable. Specifying a command
of internal-sftp will force the use of an in-process SFTP server
that requires no support files when used with ChrootDirectory.
The default is none.
GatewayPorts
Specifies whether remote hosts are allowed to connect to ports
forwarded for the client. By default, sshd(8) binds remote port
forwardings to the loopback address. This prevents other remote
hosts from connecting to forwarded ports. GatewayPorts can be
used to specify that sshd should allow remote port forwardings to
bind to non-loopback addresses, thus allowing other hosts to
connect. The argument may be no to force remote port forwardings
to be available to the local host only, yes to force remote port
forwardings to bind to the wildcard address, or clientspecified
to allow the client to select the address to which the forwarding
is bound. The default is no.
GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is no.
GSSAPICleanupCredentials
Specifies whether to automatically destroy the user's credentials
cache on logout. The default is yes.
GSSAPIStrictAcceptorCheck
Determines whether to be strict about the identity of the GSSAPI
acceptor a client authenticates against. If set to yes then the
client must authenticate against the host service on the current
hostname. If set to no then the client may authenticate against
any service key stored in the machine's default store. This
facility is provided to assist with operation on multi homed
machines. The default is yes.
HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased
authentication as a list of comma-separated patterns.
Alternately if the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character,
then the specified key types will be appended to the default set
instead of replacing them. If the specified value begins with a
M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified key types (including wildcards)
will be removed from the default set instead of replacing them.
The default for this option is:
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
The list of available key types may also be obtained using "ssh
-Q key".
HostbasedAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication
together with successful public key client host authentication is
allowed (host-based authentication). The default is no.
HostbasedUsesNameFromPacketOnly
Specifies whether or not the server will attempt to perform a
reverse name lookup when matching the name in the ~/.shosts,
~/.rhosts, and /etc/hosts.equiv files during
HostbasedAuthentication. A setting of yes means that sshd(8)
uses the name supplied by the client rather than attempting to
resolve the name from the TCP connection itself. The default is
no.
HostCertificate
Specifies a file containing a public host certificate. The
certificate's public key must match a private host key already
specified by HostKey. The default behaviour of sshd(8) is not to
load any certificates.
HostKey
Specifies a file containing a private host key used by SSH. The
defaults are /etc/ssh/ssh_host_ecdsa_key,
/etc/ssh/ssh_host_ed25519_key and /etc/ssh/ssh_host_rsa_key.
Note that sshd(8) will refuse to use a file if it is group/world-
accessible and that the HostKeyAlgorithms option restricts which
of the keys are actually used by sshd(8).
It is possible to have multiple host key files. It is also
possible to specify public host key files instead. In this case
operations on the private key will be delegated to an
ssh-agent(1).
HostKeyAgent
Identifies the UNIX-domain socket used to communicate with an
agent that has access to the private host keys. If the string
"SSH_AUTH_SOCK" is specified, the location of the socket will be
read from the SSH_AUTH_SOCK environment variable.
HostKeyAlgorithms
Specifies the host key algorithms that the server offers. The
default for this option is:
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
The list of available key types may also be obtained using "ssh
-Q key".
IgnoreRhosts
Specifies that .rhosts and .shosts files will not be used in
HostbasedAuthentication.
/etc/hosts.equiv and /etc/shosts.equiv are still used. The
default is yes.
IgnoreUserKnownHosts
Specifies whether sshd(8) should ignore the user's
~/.ssh/known_hosts during HostbasedAuthentication and use only
the system-wide known hosts file /etc/ssh/known_hosts. The
default is no.
IPQoS Specifies the IPv4 type-of-service or DSCP class for the
connection. Accepted values are af11, af12, af13, af21, af22,
af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3,
cs4, cs5, cs6, cs7, ef, lowdelay, throughput, reliability, a
numeric value, or none to use the operating system default. This
option may take one or two arguments, separated by whitespace.
If one argument is specified, it is used as the packet class
unconditionally. If two values are specified, the first is
automatically selected for interactive sessions and the second
for non-interactive sessions. The default is af21 (Low-Latency
Data) for interactive sessions and cs1 (Lower Effort) for non-
interactive sessions.
KbdInteractiveAuthentication
Specifies whether to allow keyboard-interactive authentication.
The argument to this keyword must be yes or no. The default is
to use whatever value ChallengeResponseAuthentication is set to
(by default yes).
KerberosAuthentication
Specifies whether the password provided by the user for
PasswordAuthentication will be validated through the Kerberos
KDC. To use this option, the server needs a Kerberos servtab
which allows the verification of the KDC's identity. The default
is no.
KerberosGetAFSToken
If AFS is active and the user has a Kerberos 5 TGT, attempt to
acquire an AFS token before accessing the user's home directory.
The default is no.
KerberosOrLocalPasswd
If password authentication through Kerberos fails then the
password will be validated via any additional local mechanism
such as /etc/passwd. The default is yes.
KerberosTicketCleanup
Specifies whether to automatically destroy the user's ticket
cache file on logout. The default is yes.
KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms. Multiple
algorithms must be comma-separated. Alternately if the specified
value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified methods
will be appended to the default set instead of replacing them.
If the specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y character, then the
specified methods (including wildcards) will be removed from the
default set instead of replacing them. The supported algorithms
are:
curve25519-sha256
curve25519-sha256@libssh.org
diffie-hellman-group1-sha1
diffie-hellman-group14-sha1
diffie-hellman-group14-sha256
diffie-hellman-group16-sha512
diffie-hellman-group18-sha512
diffie-hellman-group-exchange-sha1
diffie-hellman-group-exchange-sha256
ecdh-sha2-nistp256
ecdh-sha2-nistp384
ecdh-sha2-nistp521
The default is:
curve25519-sha256,curve25519-sha256@libssh.org,
ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
diffie-hellman-group-exchange-sha256,
diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
diffie-hellman-group14-sha256,diffie-hellman-group14-sha1
The list of available key exchange algorithms may also be
obtained using "ssh -Q kex".
ListenAddress
Specifies the local addresses sshd(8) should listen on. The
following forms may be used:
ListenAddress hostname|address [rdomain domain]
ListenAddress hostname:port [rdomain domain]
ListenAddress IPv4_address:port [rdomain domain]
ListenAddress [hostname|address]:port [rdomain domain]
The optional rdomain qualifier requests sshd(8) listen in an
explicit routing domain. If port is not specified, sshd will
listen on the address and all Port options specified. The
default is to listen on all local addresses on the current
default routing domain. Multiple ListenAddress options are
permitted. For more information on routing domains, see
rdomain(4).
LoginGraceTime
The server disconnects after this time if the user has not
successfully logged in. If the value is 0, there is no time
limit. The default is 120 seconds.
LogLevel
Gives the verbosity level that is used when logging messages from
sshd(8). The possible values are: QUIET, FATAL, ERROR, INFO,
VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO.
DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify
higher levels of debugging output. Logging with a DEBUG level
violates the privacy of users and is not recommended.
MACs Specifies the available MAC (message authentication code)
algorithms. The MAC algorithm is used for data integrity
protection. Multiple algorithms must be comma-separated. If the
specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character, then the specified
algorithms will be appended to the default set instead of
replacing them. If the specified value begins with a M-bM-^@M-^X-M-bM-^@M-^Y
character, then the specified algorithms (including wildcards)
will be removed from the default set instead of replacing them.
The algorithms that contain "-etm" calculate the MAC after
encryption (encrypt-then-mac). These are considered safer and
their use recommended. The supported MACs are:
hmac-md5
hmac-md5-96
hmac-sha1
hmac-sha1-96
hmac-sha2-256
hmac-sha2-512
umac-64@openssh.com
umac-128@openssh.com
hmac-md5-etm@openssh.com
hmac-md5-96-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
hmac-sha2-256-etm@openssh.com
hmac-sha2-512-etm@openssh.com
umac-64-etm@openssh.com
umac-128-etm@openssh.com
The default is:
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
hmac-sha1-etm@openssh.com,
umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-sha1
The list of available MAC algorithms may also be obtained using
"ssh -Q mac".
Match Introduces a conditional block. If all of the criteria on the
Match line are satisfied, the keywords on the following lines
override those set in the global section of the config file,
until either another Match line or the end of the file. If a
keyword appears in multiple Match blocks that are satisfied, only
the first instance of the keyword is applied.
The arguments to Match are one or more criteria-pattern pairs or
the single token All which matches all criteria. The available
criteria are User, Group, Host, LocalAddress, LocalPort, RDomain,
and Address (with RDomain representing the rdomain(4) on which
- the connection was received.)
+ the connection was received).
The match patterns may consist of single entries or comma-
separated lists and may use the wildcard and negation operators
described in the PATTERNS section of ssh_config(5).
The patterns in an Address criteria may additionally contain
addresses to match in CIDR address/masklen format, such as
192.0.2.0/24 or 2001:db8::/32. Note that the mask length
provided must be consistent with the address - it is an error to
specify a mask length that is too long for the address or one
with bits set in this host portion of the address. For example,
192.0.2.0/33 and 192.0.2.0/8, respectively.
Only a subset of keywords may be used on the lines following a
Match keyword. Available keywords are AcceptEnv,
AllowAgentForwarding, AllowGroups, AllowStreamLocalForwarding,
AllowTcpForwarding, AllowUsers, AuthenticationMethods,
AuthorizedKeysCommand, AuthorizedKeysCommandUser,
AuthorizedKeysFile, AuthorizedPrincipalsCommand,
AuthorizedPrincipalsCommandUser, AuthorizedPrincipalsFile,
Banner, ChrootDirectory, ClientAliveCountMax,
ClientAliveInterval, DenyGroups, DenyUsers, ForceCommand,
GatewayPorts, GSSAPIAuthentication, HostbasedAcceptedKeyTypes,
HostbasedAuthentication, HostbasedUsesNameFromPacketOnly, IPQoS,
KbdInteractiveAuthentication, KerberosAuthentication, LogLevel,
MaxAuthTries, MaxSessions, PasswordAuthentication,
PermitEmptyPasswords, PermitListen, PermitOpen, PermitRootLogin,
PermitTTY, PermitTunnel, PermitUserRC, PubkeyAcceptedKeyTypes,
PubkeyAuthentication, RekeyLimit, RevokedKeys, RDomain, SetEnv,
StreamLocalBindMask, StreamLocalBindUnlink, TrustedUserCAKeys,
X11DisplayOffset, X11Forwarding and X11UseLocalHost.
MaxAuthTries
Specifies the maximum number of authentication attempts permitted
per connection. Once the number of failures reaches half this
value, additional failures are logged. The default is 6.
MaxSessions
Specifies the maximum number of open shell, login or subsystem
(e.g. sftp) sessions permitted per network connection. Multiple
sessions may be established by clients that support connection
multiplexing. Setting MaxSessions to 1 will effectively disable
session multiplexing, whereas setting it to 0 will prevent all
shell, login and subsystem sessions while still permitting
forwarding. The default is 10.
MaxStartups
Specifies the maximum number of concurrent unauthenticated
connections to the SSH daemon. Additional connections will be
dropped until authentication succeeds or the LoginGraceTime
expires for a connection. The default is 10:30:100.
Alternatively, random early drop can be enabled by specifying the
three colon separated values start:rate:full (e.g. "10:30:60").
sshd(8) will refuse connection attempts with a probability of
rate/100 (30%) if there are currently start (10) unauthenticated
connections. The probability increases linearly and all
connection attempts are refused if the number of unauthenticated
connections reaches full (60).
PasswordAuthentication
Specifies whether password authentication is allowed. The
default is yes.
PermitEmptyPasswords
When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings. The
default is no.
PermitListen
Specifies the addresses/ports on which a remote TCP port
forwarding may listen. The listen specification must be one of
the following forms:
PermitListen port
PermitListen host:port
Multiple permissions may be specified by separating them with
whitespace. An argument of any can be used to remove all
restrictions and permit any listen requests. An argument of none
can be used to prohibit all listen requests. The host name may
contain wildcards as described in the PATTERNS section in
ssh_config(5). The wildcard M-bM-^@M-^X*M-bM-^@M-^Y can also be used in place of a
port number to allow all ports. By default all port forwarding
listen requests are permitted. Note that the GatewayPorts option
may further restrict which addresses may be listened on. Note
also that ssh(1) will request a listen host of M-bM-^@M-^\localhostM-bM-^@M-^] if no
- listen host was specifically requested, and this this name is
- treated differently to explicit localhost addresses of
- M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and M-bM-^@M-^\::1M-bM-^@M-^].
+ listen host was specifically requested, and this name is treated
+ differently to explicit localhost addresses of M-bM-^@M-^\127.0.0.1M-bM-^@M-^] and
+ M-bM-^@M-^\::1M-bM-^@M-^].
PermitOpen
Specifies the destinations to which TCP port forwarding is
permitted. The forwarding specification must be one of the
following forms:
PermitOpen host:port
PermitOpen IPv4_addr:port
PermitOpen [IPv6_addr]:port
Multiple forwards may be specified by separating them with
whitespace. An argument of any can be used to remove all
restrictions and permit any forwarding requests. An argument of
none can be used to prohibit all forwarding requests. The
wildcard M-bM-^@M-^X*M-bM-^@M-^Y can be used for host or port to allow all hosts or
ports, respectively. By default all port forwarding requests are
permitted.
PermitRootLogin
Specifies whether root can log in using ssh(1). The argument
must be yes, prohibit-password, forced-commands-only, or no. The
default is prohibit-password.
If this option is set to prohibit-password (or its deprecated
alias, without-password), password and keyboard-interactive
authentication are disabled for root.
If this option is set to forced-commands-only, root login with
public key authentication will be allowed, but only if the
command option has been specified (which may be useful for taking
remote backups even if root login is normally not allowed). All
other authentication methods are disabled for root.
If this option is set to no, root is not allowed to log in.
PermitTTY
Specifies whether pty(4) allocation is permitted. The default is
yes.
PermitTunnel
Specifies whether tun(4) device forwarding is allowed. The
argument must be yes, point-to-point (layer 3), ethernet (layer
2), or no. Specifying yes permits both point-to-point and
ethernet. The default is no.
Independent of this setting, the permissions of the selected
tun(4) device must allow access to the user.
PermitUserEnvironment
Specifies whether ~/.ssh/environment and environment= options in
~/.ssh/authorized_keys are processed by sshd(8). Valid options
are yes, no or a pattern-list specifying which environment
variable names to accept (for example "LANG,LC_*"). The default
is no. Enabling environment processing may enable users to
bypass access restrictions in some configurations using
mechanisms such as LD_PRELOAD.
PermitUserRC
Specifies whether any ~/.ssh/rc file is executed. The default is
yes.
PidFile
Specifies the file that contains the process ID of the SSH
daemon, or none to not write one. The default is
/var/run/sshd.pid.
Port Specifies the port number that sshd(8) listens on. The default
is 22. Multiple options of this type are permitted. See also
ListenAddress.
PrintLastLog
Specifies whether sshd(8) should print the date and time of the
last user login when a user logs in interactively. The default
is yes.
PrintMotd
Specifies whether sshd(8) should print /etc/motd when a user logs
in interactively. (On some systems it is also printed by the
shell, /etc/profile, or equivalent.) The default is yes.
PubkeyAcceptedKeyTypes
Specifies the key types that will be accepted for public key
authentication as a list of comma-separated patterns.
Alternately if the specified value begins with a M-bM-^@M-^X+M-bM-^@M-^Y character,
then the specified key types will be appended to the default set
instead of replacing them. If the specified value begins with a
M-bM-^@M-^X-M-bM-^@M-^Y character, then the specified key types (including wildcards)
will be removed from the default set instead of replacing them.
The default for this option is:
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
The list of available key types may also be obtained using "ssh
-Q key".
PubkeyAuthentication
Specifies whether public key authentication is allowed. The
default is yes.
RekeyLimit
Specifies the maximum amount of data that may be transmitted
before the session key is renegotiated, optionally followed a
maximum amount of time that may pass before the session key is
renegotiated. The first argument is specified in bytes and may
have a suffix of M-bM-^@M-^XKM-bM-^@M-^Y, M-bM-^@M-^XMM-bM-^@M-^Y, or M-bM-^@M-^XGM-bM-^@M-^Y to indicate Kilobytes,
Megabytes, or Gigabytes, respectively. The default is between
M-bM-^@M-^X1GM-bM-^@M-^Y and M-bM-^@M-^X4GM-bM-^@M-^Y, depending on the cipher. The optional second
value is specified in seconds and may use any of the units
documented in the TIME FORMATS section. The default value for
RekeyLimit is default none, which means that rekeying is
performed after the cipher's default amount of data has been sent
or received and no time based rekeying is done.
RevokedKeys
Specifies revoked public keys file, or none to not use one. Keys
listed in this file will be refused for public key
authentication. Note that if this file is not readable, then
public key authentication will be refused for all users. Keys
may be specified as a text file, listing one public key per line,
or as an OpenSSH Key Revocation List (KRL) as generated by
ssh-keygen(1). For more information on KRLs, see the KEY
REVOCATION LISTS section in ssh-keygen(1).
RDomain
Specifies an explicit routing domain that is applied after
authentication has completed. The user session, as well and any
forwarded or listening IP sockets, will be bound to this
rdomain(4). If the routing domain is set to %D, then the domain
in which the incoming connection was received will be applied.
SetEnv Specifies one or more environment variables to set in child
sessions started by sshd(8) as M-bM-^@M-^\NAME=VALUEM-bM-^@M-^]. The environment
value may be quoted (e.g. if it contains whitespace characters).
Environment variables set by SetEnv override the default
environment and any variables specified by the user via AcceptEnv
or PermitUserEnvironment.
StreamLocalBindMask
Sets the octal file creation mode mask (umask) used when creating
a Unix-domain socket file for local or remote port forwarding.
This option is only used for port forwarding to a Unix-domain
socket file.
The default value is 0177, which creates a Unix-domain socket
file that is readable and writable only by the owner. Note that
not all operating systems honor the file mode on Unix-domain
socket files.
StreamLocalBindUnlink
Specifies whether to remove an existing Unix-domain socket file
for local or remote port forwarding before creating a new one.
If the socket file already exists and StreamLocalBindUnlink is
not enabled, sshd will be unable to forward the port to the Unix-
domain socket file. This option is only used for port forwarding
to a Unix-domain socket file.
The argument must be yes or no. The default is no.
StrictModes
Specifies whether sshd(8) should check file modes and ownership
of the user's files and home directory before accepting login.
This is normally desirable because novices sometimes accidentally
leave their directory or files world-writable. The default is
yes. Note that this does not apply to ChrootDirectory, whose
permissions and ownership are checked unconditionally.
Subsystem
Configures an external subsystem (e.g. file transfer daemon).
Arguments should be a subsystem name and a command (with optional
arguments) to execute upon subsystem request.
The command sftp-server implements the SFTP file transfer
subsystem.
Alternately the name internal-sftp implements an in-process SFTP
server. This may simplify configurations using ChrootDirectory
to force a different filesystem root on clients.
By default no subsystems are defined.
SyslogFacility
Gives the facility code that is used when logging messages from
sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
default is AUTH.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
to the other side. If they are sent, death of the connection or
crash of one of the machines will be properly noticed. However,
this means that connections will die if the route is down
temporarily, and some people find it annoying. On the other
hand, if TCP keepalives are not sent, sessions may hang
indefinitely on the server, leaving "ghost" users and consuming
server resources.
The default is yes (to send TCP keepalive messages), and the
server will notice if the network goes down or the client host
crashes. This avoids infinitely hanging sessions.
To disable TCP keepalive messages, the value should be set to no.
TrustedUserCAKeys
Specifies a file containing public keys of certificate
authorities that are trusted to sign user certificates for
authentication, or none to not use one. Keys are listed one per
line; empty lines and comments starting with M-bM-^@M-^X#M-bM-^@M-^Y are allowed. If
a certificate is presented for authentication and has its signing
CA key listed in this file, then it may be used for
authentication for any user listed in the certificate's
principals list. Note that certificates that lack a list of
principals will not be permitted for authentication using
TrustedUserCAKeys. For more details on certificates, see the
CERTIFICATES section in ssh-keygen(1).
UseDNS Specifies whether sshd(8) should look up the remote host name,
and to check that the resolved host name for the remote IP
address maps back to the very same IP address.
If this option is set to no (the default) then only addresses and
not host names may be used in ~/.ssh/authorized_keys from and
sshd_config Match Host directives.
UsePAM Enables the Pluggable Authentication Module interface. If set to
yes this will enable PAM authentication using
ChallengeResponseAuthentication and PasswordAuthentication in
addition to PAM account and session module processing for all
authentication types.
Because PAM challenge-response authentication usually serves an
equivalent role to password authentication, you should disable
either PasswordAuthentication or ChallengeResponseAuthentication.
If UsePAM is enabled, you will not be able to run sshd(8) as a
non-root user. The default is no.
VersionAddendum
Optionally specifies additional text to append to the SSH
protocol banner sent by the server upon connection. The default
is none.
X11DisplayOffset
Specifies the first display number available for sshd(8)'s X11
forwarding. This prevents sshd from interfering with real X11
servers. The default is 10.
X11Forwarding
Specifies whether X11 forwarding is permitted. The argument must
be yes or no. The default is no.
When X11 forwarding is enabled, there may be additional exposure
to the server and to client displays if the sshd(8) proxy display
is configured to listen on the wildcard address (see
X11UseLocalhost), though this is not the default. Additionally,
the authentication spoofing and authentication data verification
and substitution occur on the client side. The security risk of
using X11 forwarding is that the client's X11 display server may
be exposed to attack when the SSH client requests forwarding (see
the warnings for ForwardX11 in ssh_config(5)). A system
administrator may have a stance in which they want to protect
clients that may expose themselves to attack by unwittingly
requesting X11 forwarding, which can warrant a no setting.
Note that disabling X11 forwarding does not prevent users from
forwarding X11 traffic, as users can always install their own
forwarders.
X11UseLocalhost
Specifies whether sshd(8) should bind the X11 forwarding server
to the loopback address or to the wildcard address. By default,
sshd binds the forwarding server to the loopback address and sets
the hostname part of the DISPLAY environment variable to
localhost. This prevents remote hosts from connecting to the
proxy display. However, some older X11 clients may not function
with this configuration. X11UseLocalhost may be set to no to
specify that the forwarding server should be bound to the
wildcard address. The argument must be yes or no. The default
is yes.
XAuthLocation
Specifies the full pathname of the xauth(1) program, or none to
not use one. The default is /usr/X11R6/bin/xauth.
TIME FORMATS
sshd(8) command-line arguments and configuration file options that
specify time may be expressed using a sequence of the form:
time[qualifier], where time is a positive integer value and qualifier is
one of the following:
M-bM-^_M-(noneM-bM-^_M-) seconds
s | S seconds
m | M minutes
h | H hours
d | D days
w | W weeks
Each member of the sequence is added together to calculate the total time
value.
Time format examples:
600 600 seconds (10 minutes)
10m 10 minutes
1h30m 1 hour 30 minutes (90 minutes)
TOKENS
Arguments to some keywords can make use of tokens, which are expanded at
runtime:
%% A literal M-bM-^@M-^X%M-bM-^@M-^Y.
%D The routing domain in which the incoming connection was
received.
%F The fingerprint of the CA key.
%f The fingerprint of the key or certificate.
%h The home directory of the user.
%i The key ID in the certificate.
%K The base64-encoded CA key.
%k The base64-encoded key or certificate for authentication.
%s The serial number of the certificate.
%T The type of the CA key.
%t The key or certificate type.
%U The numeric user ID of the target user.
%u The username.
AuthorizedKeysCommand accepts the tokens %%, %f, %h, %k, %t, %U, and %u.
AuthorizedKeysFile accepts the tokens %%, %h, %U, and %u.
AuthorizedPrincipalsCommand accepts the tokens %%, %F, %f, %h, %i, %K,
%k, %s, %T, %t, %U, and %u.
AuthorizedPrincipalsFile accepts the tokens %%, %h, %U, and %u.
ChrootDirectory accepts the tokens %%, %h, %U, and %u.
RoutingDomain accepts the token %D.
FILES
/etc/ssh/sshd_config
Contains configuration data for sshd(8). This file should be
writable by root only, but it is recommended (though not
necessary) that it be world-readable.
SEE ALSO
sftp-server(8), sshd(8)
AUTHORS
OpenSSH is a derivative of the original and free ssh 1.2.12 release by
Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo
de Raadt and Dug Song removed many bugs, re-added newer features and
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support
for privilege separation.
-OpenBSD 6.4 September 20, 2018 OpenBSD 6.4
+OpenBSD 6.5 March 22, 2019 OpenBSD 6.5
diff --git a/sshd_config.5 b/sshd_config.5
index c6484370b4be..b224f29297ec 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -1,1822 +1,1822 @@
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" All rights reserved
.\"
.\" As far as I am concerned, the code I have written for this software
.\" can be used freely for any purpose. Any derived versions of this
.\" software must be clearly marked as such, and if the derived work is
.\" incompatible with the protocol description in the RFC file, it must be
.\" called by a name other than "ssh" or "Secure Shell".
.\"
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: sshd_config.5,v 1.282 2018/09/20 03:28:06 djm Exp $
-.Dd $Mdocdate: September 20 2018 $
+.\" $OpenBSD: sshd_config.5,v 1.284 2019/03/22 20:58:34 jmc Exp $
+.Dd $Mdocdate: March 22 2019 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
.Nm sshd_config
.Nd OpenSSH SSH daemon configuration file
.Sh DESCRIPTION
.Xr sshd 8
reads configuration data from
.Pa /etc/ssh/sshd_config
(or the file specified with
.Fl f
on the command line).
The file contains keyword-argument pairs, one per line.
For each keyword, the first obtained value will be used.
Lines starting with
.Ql #
and empty lines are interpreted as comments.
Arguments may optionally be enclosed in double quotes
.Pq \&"
in order to represent arguments containing spaces.
.Pp
The possible
keywords and their meanings are as follows (note that
keywords are case-insensitive and arguments are case-sensitive):
.Bl -tag -width Ds
.It Cm AcceptEnv
Specifies what environment variables sent by the client will be copied into
the session's
.Xr environ 7 .
See
.Cm SendEnv
and
.Cm SetEnv
in
.Xr ssh_config 5
for how to configure the client.
The
.Ev TERM
environment variable is always accepted whenever the client
requests a pseudo-terminal as it is required by the protocol.
Variables are specified by name, which may contain the wildcard characters
.Ql *
and
.Ql \&? .
Multiple environment variables may be separated by whitespace or spread
across multiple
.Cm AcceptEnv
directives.
Be warned that some environment variables could be used to bypass restricted
user environments.
For this reason, care should be taken in the use of this directive.
The default is not to accept any environment variables.
.It Cm AddressFamily
Specifies which address family should be used by
.Xr sshd 8 .
Valid arguments are
.Cm any
(the default),
.Cm inet
(use IPv4 only), or
.Cm inet6
(use IPv6 only).
.It Cm AllowAgentForwarding
Specifies whether
.Xr ssh-agent 1
forwarding is permitted.
The default is
.Cm yes .
Note that disabling agent forwarding does not improve security
unless users are also denied shell access, as they can always install
their own forwarders.
.It Cm AllowGroups
This keyword can be followed by a list of group name patterns, separated
by spaces.
If specified, login is allowed only for users whose primary
group or supplementary group list matches one of the patterns.
Only group names are valid; a numerical group ID is not recognized.
By default, login is allowed for all groups.
The allow/deny directives are processed in the following order:
.Cm DenyUsers ,
.Cm AllowUsers ,
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
.Pp
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
.It Cm AllowStreamLocalForwarding
Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
The available options are
.Cm yes
(the default)
or
.Cm all
to allow StreamLocal forwarding,
.Cm no
to prevent all StreamLocal forwarding,
.Cm local
to allow local (from the perspective of
.Xr ssh 1 )
forwarding only or
.Cm remote
to allow remote forwarding only.
Note that disabling StreamLocal forwarding does not improve security unless
users are also denied shell access, as they can always install their
own forwarders.
.It Cm AllowTcpForwarding
Specifies whether TCP forwarding is permitted.
The available options are
.Cm yes
(the default)
or
.Cm all
to allow TCP forwarding,
.Cm no
to prevent all TCP forwarding,
.Cm local
to allow local (from the perspective of
.Xr ssh 1 )
forwarding only or
.Cm remote
to allow remote forwarding only.
Note that disabling TCP forwarding does not improve security unless
users are also denied shell access, as they can always install their
own forwarders.
.It Cm AllowUsers
This keyword can be followed by a list of user name patterns, separated
by spaces.
If specified, login is allowed only for user names that
match one of the patterns.
Only user names are valid; a numerical user ID is not recognized.
By default, login is allowed for all users.
If the pattern takes the form USER@HOST then USER and HOST
are separately checked, restricting logins to particular
users from particular hosts.
HOST criteria may additionally contain addresses to match in CIDR
address/masklen format.
The allow/deny directives are processed in the following order:
.Cm DenyUsers ,
.Cm AllowUsers ,
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
.Pp
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
.It Cm AuthenticationMethods
Specifies the authentication methods that must be successfully completed
for a user to be granted access.
This option must be followed by one or more lists of comma-separated
authentication method names, or by the single string
.Cm any
to indicate the default behaviour of accepting any single authentication
method.
If the default is overridden, then successful authentication requires
completion of every method in at least one of these lists.
.Pp
For example,
.Qq publickey,password publickey,keyboard-interactive
would require the user to complete public key authentication, followed by
either password or keyboard interactive authentication.
Only methods that are next in one or more lists are offered at each stage,
so for this example it would not be possible to attempt password or
keyboard-interactive authentication before public key.
.Pp
For keyboard interactive authentication it is also possible to
restrict authentication to a specific device by appending a
colon followed by the device identifier
.Cm bsdauth
or
.Cm pam .
depending on the server configuration.
For example,
.Qq keyboard-interactive:bsdauth
would restrict keyboard interactive authentication to the
.Cm bsdauth
device.
.Pp
If the publickey method is listed more than once,
.Xr sshd 8
verifies that keys that have been used successfully are not reused for
subsequent authentications.
For example,
.Qq publickey,publickey
requires successful authentication using two different public keys.
.Pp
Note that each authentication method listed should also be explicitly enabled
in the configuration.
.Pp
The available authentication methods are:
.Qq gssapi-with-mic ,
.Qq hostbased ,
.Qq keyboard-interactive ,
.Qq none
(used for access to password-less accounts when
.Cm PermitEmptyPasswords
is enabled),
.Qq password
and
.Qq publickey .
.It Cm AuthorizedKeysCommand
Specifies a program to be used to look up the user's public keys.
The program must be owned by root, not writable by group or others and
specified by an absolute path.
Arguments to
.Cm AuthorizedKeysCommand
accept the tokens described in the
.Sx TOKENS
section.
If no arguments are specified then the username of the target user is used.
.Pp
The program should produce on standard output zero or
more lines of authorized_keys output (see
.Sx AUTHORIZED_KEYS
in
.Xr sshd 8 ) .
If a key supplied by
.Cm AuthorizedKeysCommand
does not successfully authenticate
and authorize the user then public key authentication continues using the usual
.Cm AuthorizedKeysFile
files.
By default, no
.Cm AuthorizedKeysCommand
is run.
.It Cm AuthorizedKeysCommandUser
Specifies the user under whose account the
.Cm AuthorizedKeysCommand
is run.
It is recommended to use a dedicated user that has no other role on the host
than running authorized keys commands.
If
.Cm AuthorizedKeysCommand
is specified but
.Cm AuthorizedKeysCommandUser
is not, then
.Xr sshd 8
will refuse to start.
.It Cm AuthorizedKeysFile
Specifies the file that contains the public keys used for user authentication.
The format is described in the
.Sx AUTHORIZED_KEYS FILE FORMAT
section of
.Xr sshd 8 .
Arguments to
.Cm AuthorizedKeysFile
accept the tokens described in the
.Sx TOKENS
section.
After expansion,
.Cm AuthorizedKeysFile
is taken to be an absolute path or one relative to the user's home
directory.
Multiple files may be listed, separated by whitespace.
Alternately this option may be set to
.Cm none
to skip checking for user keys in files.
The default is
.Qq .ssh/authorized_keys .ssh/authorized_keys2 .
.It Cm AuthorizedPrincipalsCommand
Specifies a program to be used to generate the list of allowed
certificate principals as per
.Cm AuthorizedPrincipalsFile .
The program must be owned by root, not writable by group or others and
specified by an absolute path.
Arguments to
.Cm AuthorizedPrincipalsCommand
accept the tokens described in the
.Sx TOKENS
section.
If no arguments are specified then the username of the target user is used.
.Pp
The program should produce on standard output zero or
more lines of
.Cm AuthorizedPrincipalsFile
output.
If either
.Cm AuthorizedPrincipalsCommand
or
.Cm AuthorizedPrincipalsFile
is specified, then certificates offered by the client for authentication
must contain a principal that is listed.
By default, no
.Cm AuthorizedPrincipalsCommand
is run.
.It Cm AuthorizedPrincipalsCommandUser
Specifies the user under whose account the
.Cm AuthorizedPrincipalsCommand
is run.
It is recommended to use a dedicated user that has no other role on the host
than running authorized principals commands.
If
.Cm AuthorizedPrincipalsCommand
is specified but
.Cm AuthorizedPrincipalsCommandUser
is not, then
.Xr sshd 8
will refuse to start.
.It Cm AuthorizedPrincipalsFile
Specifies a file that lists principal names that are accepted for
certificate authentication.
When using certificates signed by a key listed in
.Cm TrustedUserCAKeys ,
this file lists names, one of which must appear in the certificate for it
to be accepted for authentication.
Names are listed one per line preceded by key options (as described in
.Sx AUTHORIZED_KEYS FILE FORMAT
in
.Xr sshd 8 ) .
Empty lines and comments starting with
.Ql #
are ignored.
.Pp
Arguments to
.Cm AuthorizedPrincipalsFile
accept the tokens described in the
.Sx TOKENS
section.
After expansion,
.Cm AuthorizedPrincipalsFile
is taken to be an absolute path or one relative to the user's home directory.
The default is
.Cm none ,
i.e. not to use a principals file \(en in this case, the username
of the user must appear in a certificate's principals list for it to be
accepted.
.Pp
Note that
.Cm AuthorizedPrincipalsFile
is only used when authentication proceeds using a CA listed in
.Cm TrustedUserCAKeys
and is not consulted for certification authorities trusted via
.Pa ~/.ssh/authorized_keys ,
though the
.Cm principals=
key option offers a similar facility (see
.Xr sshd 8
for details).
.It Cm Banner
The contents of the specified file are sent to the remote user before
authentication is allowed.
If the argument is
.Cm none
then no banner is displayed.
By default, no banner is displayed.
.It Cm CASignatureAlgorithms
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
The default is:
.Bd -literal -offset indent
ecdsa-sha2-nistp256.ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
Certificates signed using other algorithms will not be accepted for
public key or host-based authentication.
.It Cm ChallengeResponseAuthentication
Specifies whether challenge-response authentication is allowed (e.g. via
PAM or through authentication styles supported in
.Xr login.conf 5 )
The default is
.Cm yes .
.It Cm ChrootDirectory
Specifies the pathname of a directory to
.Xr chroot 2
to after authentication.
At session startup
.Xr sshd 8
checks that all components of the pathname are root-owned directories
which are not writable by any other user or group.
After the chroot,
.Xr sshd 8
changes the working directory to the user's home directory.
Arguments to
.Cm ChrootDirectory
accept the tokens described in the
.Sx TOKENS
section.
.Pp
The
.Cm ChrootDirectory
must contain the necessary files and directories to support the
user's session.
For an interactive session this requires at least a shell, typically
.Xr sh 1 ,
and basic
.Pa /dev
nodes such as
.Xr null 4 ,
.Xr zero 4 ,
.Xr stdin 4 ,
.Xr stdout 4 ,
.Xr stderr 4 ,
and
.Xr tty 4
devices.
For file transfer sessions using SFTP
no additional configuration of the environment is necessary if the in-process
sftp-server is used,
though sessions which use logging may require
.Pa /dev/log
inside the chroot directory on some operating systems (see
.Xr sftp-server 8
for details).
.Pp
For safety, it is very important that the directory hierarchy be
prevented from modification by other processes on the system (especially
those outside the jail).
Misconfiguration can lead to unsafe environments which
.Xr sshd 8
cannot detect.
.Pp
The default is
.Cm none ,
indicating not to
.Xr chroot 2 .
.It Cm Ciphers
Specifies the ciphers allowed.
Multiple ciphers must be comma-separated.
If the specified value begins with a
.Sq +
character, then the specified ciphers will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified ciphers (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The supported ciphers are:
.Pp
.Bl -item -compact -offset indent
.It
3des-cbc
.It
aes128-cbc
.It
aes192-cbc
.It
aes256-cbc
.It
aes128-ctr
.It
aes192-ctr
.It
aes256-ctr
.It
aes128-gcm@openssh.com
.It
aes256-gcm@openssh.com
.It
chacha20-poly1305@openssh.com
.El
.Pp
The default is:
.Bd -literal -offset indent
chacha20-poly1305@openssh.com,
aes128-ctr,aes192-ctr,aes256-ctr,
aes128-gcm@openssh.com,aes256-gcm@openssh.com
.Ed
.Pp
The list of available ciphers may also be obtained using
.Qq ssh -Q cipher .
.It Cm ClientAliveCountMax
Sets the number of client alive messages which may be sent without
.Xr sshd 8
receiving any messages back from the client.
If this threshold is reached while client alive messages are being sent,
sshd will disconnect the client, terminating the session.
It is important to note that the use of client alive messages is very
different from
.Cm TCPKeepAlive .
The client alive messages are sent through the encrypted channel
and therefore will not be spoofable.
The TCP keepalive option enabled by
.Cm TCPKeepAlive
is spoofable.
The client alive mechanism is valuable when the client or
server depend on knowing when a connection has become inactive.
.Pp
The default value is 3.
If
.Cm ClientAliveInterval
is set to 15, and
.Cm ClientAliveCountMax
is left at the default, unresponsive SSH clients
will be disconnected after approximately 45 seconds.
.It Cm ClientAliveInterval
Sets a timeout interval in seconds after which if no data has been received
from the client,
.Xr sshd 8
will send a message through the encrypted
channel to request a response from the client.
The default
is 0, indicating that these messages will not be sent to the client.
.It Cm Compression
Specifies whether compression is enabled after
the user has authenticated successfully.
The argument must be
.Cm yes ,
.Cm delayed
(a legacy synonym for
.Cm yes )
or
.Cm no .
The default is
.Cm yes .
.It Cm DenyGroups
This keyword can be followed by a list of group name patterns, separated
by spaces.
Login is disallowed for users whose primary group or supplementary
group list matches one of the patterns.
Only group names are valid; a numerical group ID is not recognized.
By default, login is allowed for all groups.
The allow/deny directives are processed in the following order:
.Cm DenyUsers ,
.Cm AllowUsers ,
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
.Pp
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
.It Cm DenyUsers
This keyword can be followed by a list of user name patterns, separated
by spaces.
Login is disallowed for user names that match one of the patterns.
Only user names are valid; a numerical user ID is not recognized.
By default, login is allowed for all users.
If the pattern takes the form USER@HOST then USER and HOST
are separately checked, restricting logins to particular
users from particular hosts.
HOST criteria may additionally contain addresses to match in CIDR
address/masklen format.
The allow/deny directives are processed in the following order:
.Cm DenyUsers ,
.Cm AllowUsers ,
.Cm DenyGroups ,
and finally
.Cm AllowGroups .
.Pp
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
.It Cm DisableForwarding
Disables all forwarding features, including X11,
.Xr ssh-agent 1 ,
TCP and StreamLocal.
This option overrides all other forwarding-related options and may
simplify restricted configurations.
.It Cm ExposeAuthInfo
Writes a temporary file containing a list of authentication methods and
public credentials (e.g. keys) used to authenticate the user.
The location of the file is exposed to the user session through the
.Ev SSH_USER_AUTH
environment variable.
The default is
.Cm no .
.It Cm FingerprintHash
Specifies the hash algorithm used when logging key fingerprints.
Valid options are:
.Cm md5
and
.Cm sha256 .
The default is
.Cm sha256 .
.It Cm ForceCommand
Forces the execution of the command specified by
.Cm ForceCommand ,
ignoring any command supplied by the client and
.Pa ~/.ssh/rc
if present.
The command is invoked by using the user's login shell with the -c option.
This applies to shell, command, or subsystem execution.
It is most useful inside a
.Cm Match
block.
The command originally supplied by the client is available in the
.Ev SSH_ORIGINAL_COMMAND
environment variable.
Specifying a command of
.Cm internal-sftp
will force the use of an in-process SFTP server that requires no support
files when used with
.Cm ChrootDirectory .
The default is
.Cm none .
.It Cm GatewayPorts
Specifies whether remote hosts are allowed to connect to ports
forwarded for the client.
By default,
.Xr sshd 8
binds remote port forwardings to the loopback address.
This prevents other remote hosts from connecting to forwarded ports.
.Cm GatewayPorts
can be used to specify that sshd
should allow remote port forwardings to bind to non-loopback addresses, thus
allowing other hosts to connect.
The argument may be
.Cm no
to force remote port forwardings to be available to the local host only,
.Cm yes
to force remote port forwardings to bind to the wildcard address, or
.Cm clientspecified
to allow the client to select the address to which the forwarding is bound.
The default is
.Cm no .
.It Cm GSSAPIAuthentication
Specifies whether user authentication based on GSSAPI is allowed.
The default is
.Cm no .
.It Cm GSSAPICleanupCredentials
Specifies whether to automatically destroy the user's credentials cache
on logout.
The default is
.Cm yes .
.It Cm GSSAPIStrictAcceptorCheck
Determines whether to be strict about the identity of the GSSAPI acceptor
a client authenticates against.
If set to
.Cm yes
then the client must authenticate against the host
service on the current hostname.
If set to
.Cm no
then the client may authenticate against any service key stored in the
machine's default store.
This facility is provided to assist with operation on multi homed machines.
The default is
.Cm yes .
.It Cm HostbasedAcceptedKeyTypes
Specifies the key types that will be accepted for hostbased authentication
as a list of comma-separated patterns.
Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
.It Cm HostbasedAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful public key client host authentication is allowed
(host-based authentication).
The default is
.Cm no .
.It Cm HostbasedUsesNameFromPacketOnly
Specifies whether or not the server will attempt to perform a reverse
name lookup when matching the name in the
.Pa ~/.shosts ,
.Pa ~/.rhosts ,
and
.Pa /etc/hosts.equiv
files during
.Cm HostbasedAuthentication .
A setting of
.Cm yes
means that
.Xr sshd 8
uses the name supplied by the client rather than
attempting to resolve the name from the TCP connection itself.
The default is
.Cm no .
.It Cm HostCertificate
Specifies a file containing a public host certificate.
The certificate's public key must match a private host key already specified
by
.Cm HostKey .
The default behaviour of
.Xr sshd 8
is not to load any certificates.
.It Cm HostKey
Specifies a file containing a private host key
used by SSH.
The defaults are
.Pa /etc/ssh/ssh_host_ecdsa_key ,
.Pa /etc/ssh/ssh_host_ed25519_key
and
.Pa /etc/ssh/ssh_host_rsa_key .
.Pp
Note that
.Xr sshd 8
will refuse to use a file if it is group/world-accessible
and that the
.Cm HostKeyAlgorithms
option restricts which of the keys are actually used by
.Xr sshd 8 .
.Pp
It is possible to have multiple host key files.
It is also possible to specify public host key files instead.
In this case operations on the private key will be delegated
to an
.Xr ssh-agent 1 .
.It Cm HostKeyAgent
Identifies the UNIX-domain socket used to communicate
with an agent that has access to the private host keys.
If the string
.Qq SSH_AUTH_SOCK
is specified, the location of the socket will be read from the
.Ev SSH_AUTH_SOCK
environment variable.
.It Cm HostKeyAlgorithms
Specifies the host key algorithms
that the server offers.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
.It Cm IgnoreRhosts
Specifies that
.Pa .rhosts
and
.Pa .shosts
files will not be used in
.Cm HostbasedAuthentication .
.Pp
.Pa /etc/hosts.equiv
and
.Pa /etc/shosts.equiv
are still used.
The default is
.Cm yes .
.It Cm IgnoreUserKnownHosts
Specifies whether
.Xr sshd 8
should ignore the user's
.Pa ~/.ssh/known_hosts
during
.Cm HostbasedAuthentication
and use only the system-wide known hosts file
.Pa /etc/ssh/known_hosts .
The default is
.Cm no .
.It Cm IPQoS
Specifies the IPv4 type-of-service or DSCP class for the connection.
Accepted values are
.Cm af11 ,
.Cm af12 ,
.Cm af13 ,
.Cm af21 ,
.Cm af22 ,
.Cm af23 ,
.Cm af31 ,
.Cm af32 ,
.Cm af33 ,
.Cm af41 ,
.Cm af42 ,
.Cm af43 ,
.Cm cs0 ,
.Cm cs1 ,
.Cm cs2 ,
.Cm cs3 ,
.Cm cs4 ,
.Cm cs5 ,
.Cm cs6 ,
.Cm cs7 ,
.Cm ef ,
.Cm lowdelay ,
.Cm throughput ,
.Cm reliability ,
a numeric value, or
.Cm none
to use the operating system default.
This option may take one or two arguments, separated by whitespace.
If one argument is specified, it is used as the packet class unconditionally.
If two values are specified, the first is automatically selected for
interactive sessions and the second for non-interactive sessions.
The default is
.Cm af21
(Low-Latency Data)
for interactive sessions and
.Cm cs1
(Lower Effort)
for non-interactive sessions.
.It Cm KbdInteractiveAuthentication
Specifies whether to allow keyboard-interactive authentication.
The argument to this keyword must be
.Cm yes
or
.Cm no .
The default is to use whatever value
.Cm ChallengeResponseAuthentication
is set to
(by default
.Cm yes ) .
.It Cm KerberosAuthentication
Specifies whether the password provided by the user for
.Cm PasswordAuthentication
will be validated through the Kerberos KDC.
To use this option, the server needs a
Kerberos servtab which allows the verification of the KDC's identity.
The default is
.Cm no .
.It Cm KerberosGetAFSToken
If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire
an AFS token before accessing the user's home directory.
The default is
.Cm no .
.It Cm KerberosOrLocalPasswd
If password authentication through Kerberos fails then
the password will be validated via any additional local mechanism
such as
.Pa /etc/passwd .
The default is
.Cm yes .
.It Cm KerberosTicketCleanup
Specifies whether to automatically destroy the user's ticket cache
file on logout.
The default is
.Cm yes .
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
Alternately if the specified value begins with a
.Sq +
character, then the specified methods will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified methods (including wildcards) will be removed
from the default set instead of replacing them.
The supported algorithms are:
.Pp
.Bl -item -compact -offset indent
.It
curve25519-sha256
.It
curve25519-sha256@libssh.org
.It
diffie-hellman-group1-sha1
.It
diffie-hellman-group14-sha1
.It
diffie-hellman-group14-sha256
.It
diffie-hellman-group16-sha512
.It
diffie-hellman-group18-sha512
.It
diffie-hellman-group-exchange-sha1
.It
diffie-hellman-group-exchange-sha256
.It
ecdh-sha2-nistp256
.It
ecdh-sha2-nistp384
.It
ecdh-sha2-nistp521
.El
.Pp
The default is:
.Bd -literal -offset indent
curve25519-sha256,curve25519-sha256@libssh.org,
ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
diffie-hellman-group-exchange-sha256,
diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,
diffie-hellman-group14-sha256,diffie-hellman-group14-sha1
.Ed
.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
.It Cm ListenAddress
Specifies the local addresses
.Xr sshd 8
should listen on.
The following forms may be used:
.Pp
.Bl -item -offset indent -compact
.It
.Cm ListenAddress
.Sm off
.Ar hostname | address
.Sm on
.Op Cm rdomain Ar domain
.It
.Cm ListenAddress
.Sm off
.Ar hostname : port
.Sm on
.Op Cm rdomain Ar domain
.It
.Cm ListenAddress
.Sm off
.Ar IPv4_address : port
.Sm on
.Op Cm rdomain Ar domain
.It
.Cm ListenAddress
.Sm off
.Oo Ar hostname | address Oc : Ar port
.Sm on
.Op Cm rdomain Ar domain
.El
.Pp
The optional
.Cm rdomain
qualifier requests
.Xr sshd 8
listen in an explicit routing domain.
If
.Ar port
is not specified,
sshd will listen on the address and all
.Cm Port
options specified.
The default is to listen on all local addresses on the current default
routing domain.
Multiple
.Cm ListenAddress
options are permitted.
For more information on routing domains, see
.Xr rdomain 4 .
.It Cm LoginGraceTime
The server disconnects after this time if the user has not
successfully logged in.
If the value is 0, there is no time limit.
The default is 120 seconds.
.It Cm LogLevel
Gives the verbosity level that is used when logging messages from
.Xr sshd 8 .
The possible values are:
QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
The default is INFO.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
Logging with a DEBUG level violates the privacy of users and is not recommended.
.It Cm MACs
Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used for data integrity protection.
Multiple algorithms must be comma-separated.
If the specified value begins with a
.Sq +
character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
.Pp
The algorithms that contain
.Qq -etm
calculate the MAC after encryption (encrypt-then-mac).
These are considered safer and their use recommended.
The supported MACs are:
.Pp
.Bl -item -compact -offset indent
.It
hmac-md5
.It
hmac-md5-96
.It
hmac-sha1
.It
hmac-sha1-96
.It
hmac-sha2-256
.It
hmac-sha2-512
.It
umac-64@openssh.com
.It
umac-128@openssh.com
.It
hmac-md5-etm@openssh.com
.It
hmac-md5-96-etm@openssh.com
.It
hmac-sha1-etm@openssh.com
.It
hmac-sha1-96-etm@openssh.com
.It
hmac-sha2-256-etm@openssh.com
.It
hmac-sha2-512-etm@openssh.com
.It
umac-64-etm@openssh.com
.It
umac-128-etm@openssh.com
.El
.Pp
The default is:
.Bd -literal -offset indent
umac-64-etm@openssh.com,umac-128-etm@openssh.com,
hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
hmac-sha1-etm@openssh.com,
umac-64@openssh.com,umac-128@openssh.com,
hmac-sha2-256,hmac-sha2-512,hmac-sha1
.Ed
.Pp
The list of available MAC algorithms may also be obtained using
.Qq ssh -Q mac .
.It Cm Match
Introduces a conditional block.
If all of the criteria on the
.Cm Match
line are satisfied, the keywords on the following lines override those
set in the global section of the config file, until either another
.Cm Match
line or the end of the file.
If a keyword appears in multiple
.Cm Match
blocks that are satisfied, only the first instance of the keyword is
applied.
.Pp
The arguments to
.Cm Match
are one or more criteria-pattern pairs or the single token
.Cm All
which matches all criteria.
The available criteria are
.Cm User ,
.Cm Group ,
.Cm Host ,
.Cm LocalAddress ,
.Cm LocalPort ,
.Cm RDomain ,
and
.Cm Address
(with
.Cm RDomain
representing the
.Xr rdomain 4
-on which the connection was received.)
+on which the connection was received).
.Pp
The match patterns may consist of single entries or comma-separated
lists and may use the wildcard and negation operators described in the
.Sx PATTERNS
section of
.Xr ssh_config 5 .
.Pp
The patterns in an
.Cm Address
criteria may additionally contain addresses to match in CIDR
address/masklen format,
such as 192.0.2.0/24 or 2001:db8::/32.
Note that the mask length provided must be consistent with the address -
it is an error to specify a mask length that is too long for the address
or one with bits set in this host portion of the address.
For example, 192.0.2.0/33 and 192.0.2.0/8, respectively.
.Pp
Only a subset of keywords may be used on the lines following a
.Cm Match
keyword.
Available keywords are
.Cm AcceptEnv ,
.Cm AllowAgentForwarding ,
.Cm AllowGroups ,
.Cm AllowStreamLocalForwarding ,
.Cm AllowTcpForwarding ,
.Cm AllowUsers ,
.Cm AuthenticationMethods ,
.Cm AuthorizedKeysCommand ,
.Cm AuthorizedKeysCommandUser ,
.Cm AuthorizedKeysFile ,
.Cm AuthorizedPrincipalsCommand ,
.Cm AuthorizedPrincipalsCommandUser ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,
.Cm ChrootDirectory ,
.Cm ClientAliveCountMax ,
.Cm ClientAliveInterval ,
.Cm DenyGroups ,
.Cm DenyUsers ,
.Cm ForceCommand ,
.Cm GatewayPorts ,
.Cm GSSAPIAuthentication ,
.Cm HostbasedAcceptedKeyTypes ,
.Cm HostbasedAuthentication ,
.Cm HostbasedUsesNameFromPacketOnly ,
.Cm IPQoS ,
.Cm KbdInteractiveAuthentication ,
.Cm KerberosAuthentication ,
.Cm LogLevel ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
.Cm PasswordAuthentication ,
.Cm PermitEmptyPasswords ,
.Cm PermitListen ,
.Cm PermitOpen ,
.Cm PermitRootLogin ,
.Cm PermitTTY ,
.Cm PermitTunnel ,
.Cm PermitUserRC ,
.Cm PubkeyAcceptedKeyTypes ,
.Cm PubkeyAuthentication ,
.Cm RekeyLimit ,
.Cm RevokedKeys ,
.Cm RDomain ,
.Cm SetEnv ,
.Cm StreamLocalBindMask ,
.Cm StreamLocalBindUnlink ,
.Cm TrustedUserCAKeys ,
.Cm X11DisplayOffset ,
.Cm X11Forwarding
and
.Cm X11UseLocalHost .
.It Cm MaxAuthTries
Specifies the maximum number of authentication attempts permitted per
connection.
Once the number of failures reaches half this value,
additional failures are logged.
The default is 6.
.It Cm MaxSessions
Specifies the maximum number of open shell, login or subsystem (e.g. sftp)
sessions permitted per network connection.
Multiple sessions may be established by clients that support connection
multiplexing.
Setting
.Cm MaxSessions
to 1 will effectively disable session multiplexing, whereas setting it to 0
will prevent all shell, login and subsystem sessions while still permitting
forwarding.
The default is 10.
.It Cm MaxStartups
Specifies the maximum number of concurrent unauthenticated connections to the
SSH daemon.
Additional connections will be dropped until authentication succeeds or the
.Cm LoginGraceTime
expires for a connection.
The default is 10:30:100.
.Pp
Alternatively, random early drop can be enabled by specifying
the three colon separated values
start:rate:full (e.g. "10:30:60").
.Xr sshd 8
will refuse connection attempts with a probability of rate/100 (30%)
if there are currently start (10) unauthenticated connections.
The probability increases linearly and all connection attempts
are refused if the number of unauthenticated connections reaches full (60).
.It Cm PasswordAuthentication
Specifies whether password authentication is allowed.
The default is
.Cm yes .
.It Cm PermitEmptyPasswords
When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings.
The default is
.Cm no .
.It Cm PermitListen
Specifies the addresses/ports on which a remote TCP port forwarding may listen.
The listen specification must be one of the following forms:
.Pp
.Bl -item -offset indent -compact
.It
.Cm PermitListen
.Sm off
.Ar port
.Sm on
.It
.Cm PermitListen
.Sm off
.Ar host : port
.Sm on
.El
.Pp
Multiple permissions may be specified by separating them with whitespace.
An argument of
.Cm any
can be used to remove all restrictions and permit any listen requests.
An argument of
.Cm none
can be used to prohibit all listen requests.
The host name may contain wildcards as described in the PATTERNS section in
.Xr ssh_config 5 .
The wildcard
.Sq *
can also be used in place of a port number to allow all ports.
By default all port forwarding listen requests are permitted.
Note that the
.Cm GatewayPorts
option may further restrict which addresses may be listened on.
Note also that
.Xr ssh 1
will request a listen host of
.Dq localhost
-if no listen host was specifically requested, and this this name is
+if no listen host was specifically requested, and this name is
treated differently to explicit localhost addresses of
.Dq 127.0.0.1
and
.Dq ::1 .
.It Cm PermitOpen
Specifies the destinations to which TCP port forwarding is permitted.
The forwarding specification must be one of the following forms:
.Pp
.Bl -item -offset indent -compact
.It
.Cm PermitOpen
.Sm off
.Ar host : port
.Sm on
.It
.Cm PermitOpen
.Sm off
.Ar IPv4_addr : port
.Sm on
.It
.Cm PermitOpen
.Sm off
.Ar \&[ IPv6_addr \&] : port
.Sm on
.El
.Pp
Multiple forwards may be specified by separating them with whitespace.
An argument of
.Cm any
can be used to remove all restrictions and permit any forwarding requests.
An argument of
.Cm none
can be used to prohibit all forwarding requests.
The wildcard
.Sq *
can be used for host or port to allow all hosts or ports, respectively.
By default all port forwarding requests are permitted.
.It Cm PermitRootLogin
Specifies whether root can log in using
.Xr ssh 1 .
The argument must be
.Cm yes ,
.Cm prohibit-password ,
.Cm forced-commands-only ,
or
.Cm no .
The default is
.Cm prohibit-password .
.Pp
If this option is set to
.Cm prohibit-password
(or its deprecated alias,
.Cm without-password ) ,
password and keyboard-interactive authentication are disabled for root.
.Pp
If this option is set to
.Cm forced-commands-only ,
root login with public key authentication will be allowed,
but only if the
.Ar command
option has been specified
(which may be useful for taking remote backups even if root login is
normally not allowed).
All other authentication methods are disabled for root.
.Pp
If this option is set to
.Cm no ,
root is not allowed to log in.
.It Cm PermitTTY
Specifies whether
.Xr pty 4
allocation is permitted.
The default is
.Cm yes .
.It Cm PermitTunnel
Specifies whether
.Xr tun 4
device forwarding is allowed.
The argument must be
.Cm yes ,
.Cm point-to-point
(layer 3),
.Cm ethernet
(layer 2), or
.Cm no .
Specifying
.Cm yes
permits both
.Cm point-to-point
and
.Cm ethernet .
The default is
.Cm no .
.Pp
Independent of this setting, the permissions of the selected
.Xr tun 4
device must allow access to the user.
.It Cm PermitUserEnvironment
Specifies whether
.Pa ~/.ssh/environment
and
.Cm environment=
options in
.Pa ~/.ssh/authorized_keys
are processed by
.Xr sshd 8 .
Valid options are
.Cm yes ,
.Cm no
or a pattern-list specifying which environment variable names to accept
(for example
.Qq LANG,LC_* ) .
The default is
.Cm no .
Enabling environment processing may enable users to bypass access
restrictions in some configurations using mechanisms such as
.Ev LD_PRELOAD .
.It Cm PermitUserRC
Specifies whether any
.Pa ~/.ssh/rc
file is executed.
The default is
.Cm yes .
.It Cm PidFile
Specifies the file that contains the process ID of the
SSH daemon, or
.Cm none
to not write one.
The default is
.Pa /var/run/sshd.pid .
.It Cm Port
Specifies the port number that
.Xr sshd 8
listens on.
The default is 22.
Multiple options of this type are permitted.
See also
.Cm ListenAddress .
.It Cm PrintLastLog
Specifies whether
.Xr sshd 8
should print the date and time of the last user login when a user logs
in interactively.
The default is
.Cm yes .
.It Cm PrintMotd
Specifies whether
.Xr sshd 8
should print
.Pa /etc/motd
when a user logs in interactively.
(On some systems it is also printed by the shell,
.Pa /etc/profile ,
or equivalent.)
The default is
.Cm yes .
.It Cm PubkeyAcceptedKeyTypes
Specifies the key types that will be accepted for public key authentication
as a list of comma-separated patterns.
Alternately if the specified value begins with a
.Sq +
character, then the specified key types will be appended to the default set
instead of replacing them.
If the specified value begins with a
.Sq -
character, then the specified key types (including wildcards) will be removed
from the default set instead of replacing them.
The default for this option is:
.Bd -literal -offset 3n
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
ssh-ed25519-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
The list of available key types may also be obtained using
.Qq ssh -Q key .
.It Cm PubkeyAuthentication
Specifies whether public key authentication is allowed.
The default is
.Cm yes .
.It Cm RekeyLimit
Specifies the maximum amount of data that may be transmitted before the
session key is renegotiated, optionally followed a maximum amount of
time that may pass before the session key is renegotiated.
The first argument is specified in bytes and may have a suffix of
.Sq K ,
.Sq M ,
or
.Sq G
to indicate Kilobytes, Megabytes, or Gigabytes, respectively.
The default is between
.Sq 1G
and
.Sq 4G ,
depending on the cipher.
The optional second value is specified in seconds and may use any of the
units documented in the
.Sx TIME FORMATS
section.
The default value for
.Cm RekeyLimit
is
.Cm default none ,
which means that rekeying is performed after the cipher's default amount
of data has been sent or received and no time based rekeying is done.
.It Cm RevokedKeys
Specifies revoked public keys file, or
.Cm none
to not use one.
Keys listed in this file will be refused for public key authentication.
Note that if this file is not readable, then public key authentication will
be refused for all users.
Keys may be specified as a text file, listing one public key per line, or as
an OpenSSH Key Revocation List (KRL) as generated by
.Xr ssh-keygen 1 .
For more information on KRLs, see the KEY REVOCATION LISTS section in
.Xr ssh-keygen 1 .
.It Cm RDomain
Specifies an explicit routing domain that is applied after authentication
has completed.
The user session, as well and any forwarded or listening IP sockets,
will be bound to this
.Xr rdomain 4 .
If the routing domain is set to
.Cm \&%D ,
then the domain in which the incoming connection was received will be applied.
.It Cm SetEnv
Specifies one or more environment variables to set in child sessions started
by
.Xr sshd 8
as
.Dq NAME=VALUE .
The environment value may be quoted (e.g. if it contains whitespace
characters).
Environment variables set by
.Cm SetEnv
override the default environment and any variables specified by the user
via
.Cm AcceptEnv
or
.Cm PermitUserEnvironment .
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
used when creating a Unix-domain socket file for local or remote
port forwarding.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The default value is 0177, which creates a Unix-domain socket file that is
readable and writable only by the owner.
Note that not all operating systems honor the file mode on Unix-domain
socket files.
.It Cm StreamLocalBindUnlink
Specifies whether to remove an existing Unix-domain socket file for local
or remote port forwarding before creating a new one.
If the socket file already exists and
.Cm StreamLocalBindUnlink
is not enabled,
.Nm sshd
will be unable to forward the port to the Unix-domain socket file.
This option is only used for port forwarding to a Unix-domain socket file.
.Pp
The argument must be
.Cm yes
or
.Cm no .
The default is
.Cm no .
.It Cm StrictModes
Specifies whether
.Xr sshd 8
should check file modes and ownership of the
user's files and home directory before accepting login.
This is normally desirable because novices sometimes accidentally leave their
directory or files world-writable.
The default is
.Cm yes .
Note that this does not apply to
.Cm ChrootDirectory ,
whose permissions and ownership are checked unconditionally.
.It Cm Subsystem
Configures an external subsystem (e.g. file transfer daemon).
Arguments should be a subsystem name and a command (with optional arguments)
to execute upon subsystem request.
.Pp
The command
.Cm sftp-server
implements the SFTP file transfer subsystem.
.Pp
Alternately the name
.Cm internal-sftp
implements an in-process SFTP server.
This may simplify configurations using
.Cm ChrootDirectory
to force a different filesystem root on clients.
.Pp
By default no subsystems are defined.
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
.It Cm TCPKeepAlive
Specifies whether the system should send TCP keepalive messages to the
other side.
If they are sent, death of the connection or crash of one
of the machines will be properly noticed.
However, this means that
connections will die if the route is down temporarily, and some people
find it annoying.
On the other hand, if TCP keepalives are not sent,
sessions may hang indefinitely on the server, leaving
.Qq ghost
users and consuming server resources.
.Pp
The default is
.Cm yes
(to send TCP keepalive messages), and the server will notice
if the network goes down or the client host crashes.
This avoids infinitely hanging sessions.
.Pp
To disable TCP keepalive messages, the value should be set to
.Cm no .
.It Cm TrustedUserCAKeys
Specifies a file containing public keys of certificate authorities that are
trusted to sign user certificates for authentication, or
.Cm none
to not use one.
Keys are listed one per line; empty lines and comments starting with
.Ql #
are allowed.
If a certificate is presented for authentication and has its signing CA key
listed in this file, then it may be used for authentication for any user
listed in the certificate's principals list.
Note that certificates that lack a list of principals will not be permitted
for authentication using
.Cm TrustedUserCAKeys .
For more details on certificates, see the CERTIFICATES section in
.Xr ssh-keygen 1 .
.It Cm UseDNS
Specifies whether
.Xr sshd 8
should look up the remote host name, and to check that
the resolved host name for the remote IP address maps back to the
very same IP address.
.Pp
If this option is set to
.Cm no
(the default) then only addresses and not host names may be used in
.Pa ~/.ssh/authorized_keys
.Cm from
and
.Nm
.Cm Match
.Cm Host
directives.
.It Cm UsePAM
Enables the Pluggable Authentication Module interface.
If set to
.Cm yes
this will enable PAM authentication using
.Cm ChallengeResponseAuthentication
and
.Cm PasswordAuthentication
in addition to PAM account and session module processing for all
authentication types.
.Pp
Because PAM challenge-response authentication usually serves an equivalent
role to password authentication, you should disable either
.Cm PasswordAuthentication
or
.Cm ChallengeResponseAuthentication.
.Pp
If
.Cm UsePAM
is enabled, you will not be able to run
.Xr sshd 8
as a non-root user.
The default is
.Cm no .
.It Cm VersionAddendum
Optionally specifies additional text to append to the SSH protocol banner
sent by the server upon connection.
The default is
.Cm none .
.It Cm X11DisplayOffset
Specifies the first display number available for
.Xr sshd 8 Ns 's
X11 forwarding.
This prevents sshd from interfering with real X11 servers.
The default is 10.
.It Cm X11Forwarding
Specifies whether X11 forwarding is permitted.
The argument must be
.Cm yes
or
.Cm no .
The default is
.Cm no .
.Pp
When X11 forwarding is enabled, there may be additional exposure to
the server and to client displays if the
.Xr sshd 8
proxy display is configured to listen on the wildcard address (see
.Cm X11UseLocalhost ) ,
though this is not the default.
Additionally, the authentication spoofing and authentication data
verification and substitution occur on the client side.
The security risk of using X11 forwarding is that the client's X11
display server may be exposed to attack when the SSH client requests
forwarding (see the warnings for
.Cm ForwardX11
in
.Xr ssh_config 5 ) .
A system administrator may have a stance in which they want to
protect clients that may expose themselves to attack by unwittingly
requesting X11 forwarding, which can warrant a
.Cm no
setting.
.Pp
Note that disabling X11 forwarding does not prevent users from
forwarding X11 traffic, as users can always install their own forwarders.
.It Cm X11UseLocalhost
Specifies whether
.Xr sshd 8
should bind the X11 forwarding server to the loopback address or to
the wildcard address.
By default,
sshd binds the forwarding server to the loopback address and sets the
hostname part of the
.Ev DISPLAY
environment variable to
.Cm localhost .
This prevents remote hosts from connecting to the proxy display.
However, some older X11 clients may not function with this
configuration.
.Cm X11UseLocalhost
may be set to
.Cm no
to specify that the forwarding server should be bound to the wildcard
address.
The argument must be
.Cm yes
or
.Cm no .
The default is
.Cm yes .
.It Cm XAuthLocation
Specifies the full pathname of the
.Xr xauth 1
program, or
.Cm none
to not use one.
The default is
.Pa /usr/X11R6/bin/xauth .
.El
.Sh TIME FORMATS
.Xr sshd 8
command-line arguments and configuration file options that specify time
may be expressed using a sequence of the form:
.Sm off
.Ar time Op Ar qualifier ,
.Sm on
where
.Ar time
is a positive integer value and
.Ar qualifier
is one of the following:
.Pp
.Bl -tag -width Ds -compact -offset indent
.It Aq Cm none
seconds
.It Cm s | Cm S
seconds
.It Cm m | Cm M
minutes
.It Cm h | Cm H
hours
.It Cm d | Cm D
days
.It Cm w | Cm W
weeks
.El
.Pp
Each member of the sequence is added together to calculate
the total time value.
.Pp
Time format examples:
.Pp
.Bl -tag -width Ds -compact -offset indent
.It 600
600 seconds (10 minutes)
.It 10m
10 minutes
.It 1h30m
1 hour 30 minutes (90 minutes)
.El
.Sh TOKENS
Arguments to some keywords can make use of tokens,
which are expanded at runtime:
.Pp
.Bl -tag -width XXXX -offset indent -compact
.It %%
A literal
.Sq % .
.It \&%D
The routing domain in which the incoming connection was received.
.It %F
The fingerprint of the CA key.
.It %f
The fingerprint of the key or certificate.
.It %h
The home directory of the user.
.It %i
The key ID in the certificate.
.It %K
The base64-encoded CA key.
.It %k
The base64-encoded key or certificate for authentication.
.It %s
The serial number of the certificate.
.It \&%T
The type of the CA key.
.It %t
The key or certificate type.
.It \&%U
The numeric user ID of the target user.
.It %u
The username.
.El
.Pp
.Cm AuthorizedKeysCommand
accepts the tokens %%, %f, %h, %k, %t, %U, and %u.
.Pp
.Cm AuthorizedKeysFile
accepts the tokens %%, %h, %U, and %u.
.Pp
.Cm AuthorizedPrincipalsCommand
accepts the tokens %%, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u.
.Pp
.Cm AuthorizedPrincipalsFile
accepts the tokens %%, %h, %U, and %u.
.Pp
.Cm ChrootDirectory
accepts the tokens %%, %h, %U, and %u.
.Pp
.Cm RoutingDomain
accepts the token %D.
.Sh FILES
.Bl -tag -width Ds
.It Pa /etc/ssh/sshd_config
Contains configuration data for
.Xr sshd 8 .
This file should be writable by root only, but it is recommended
(though not necessary) that it be world-readable.
.El
.Sh SEE ALSO
.Xr sftp-server 8 ,
.Xr sshd 8
.Sh AUTHORS
.An -nosplit
OpenSSH is a derivative of the original and free
ssh 1.2.12 release by
.An Tatu Ylonen .
.An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos ,
.An Theo de Raadt
and
.An Dug Song
removed many bugs, re-added newer features and
created OpenSSH.
.An Markus Friedl
contributed the support for SSH protocol versions 1.5 and 2.0.
.An Niels Provos
and
.An Markus Friedl
contributed support for privilege separation.
diff --git a/sshkey.c b/sshkey.c
index 6555c5ef8de0..ad1957762e90 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4165 +1,4121 @@
-/* $OpenBSD: sshkey.c,v 1.72 2018/10/11 00:52:46 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.73 2019/01/21 09:54:11 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
* Copyright (c) 2010,2011 Damien Miller. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
#include <sys/types.h>
#include <netinet/in.h>
#ifdef WITH_OPENSSL
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#endif
#include "crypto_api.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <resolv.h>
#ifdef HAVE_UTIL_H
#include <util.h>
#endif /* HAVE_UTIL_H */
#include "ssh2.h"
#include "ssherr.h"
#include "misc.h"
#include "sshbuf.h"
#include "cipher.h"
#include "digest.h"
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "sshkey-xmss.h"
#include "match.h"
#include "xmss_fast.h"
#include "openbsd-compat/openssl-compat.h"
/* openssh private key file format */
#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
#define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
#define MARK_END_LEN (sizeof(MARK_END) - 1)
#define KDFNAME "bcrypt"
#define AUTH_MAGIC "openssh-key-v1"
#define SALT_LEN 16
#define DEFAULT_CIPHERNAME "aes256-ctr"
#define DEFAULT_ROUNDS 16
/* Version identification string for SSH v1 identity files. */
#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
int sshkey_private_serialize_opt(const struct sshkey *key,
struct sshbuf *buf, enum sshkey_serialize_rep);
static int sshkey_from_blob_internal(struct sshbuf *buf,
struct sshkey **keyp, int allow_cert);
static int get_sigtype(const u_char *sig, size_t siglen, char **sigtypep);
/* Supported key types */
struct keytype {
const char *name;
const char *shortname;
const char *sigalg;
int type;
int nid;
int cert;
int sigonly;
};
static const struct keytype keytypes[] = {
{ "ssh-ed25519", "ED25519", NULL, KEY_ED25519, 0, 0, 0 },
{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", NULL,
KEY_ED25519_CERT, 0, 1, 0 },
#ifdef WITH_XMSS
{ "ssh-xmss@openssh.com", "XMSS", NULL, KEY_XMSS, 0, 0, 0 },
{ "ssh-xmss-cert-v01@openssh.com", "XMSS-CERT", NULL,
KEY_XMSS_CERT, 0, 1, 0 },
#endif /* WITH_XMSS */
#ifdef WITH_OPENSSL
{ "ssh-rsa", "RSA", NULL, KEY_RSA, 0, 0, 0 },
{ "rsa-sha2-256", "RSA", NULL, KEY_RSA, 0, 0, 1 },
{ "rsa-sha2-512", "RSA", NULL, KEY_RSA, 0, 0, 1 },
{ "ssh-dss", "DSA", NULL, KEY_DSA, 0, 0, 0 },
# ifdef OPENSSL_HAS_ECC
{ "ecdsa-sha2-nistp256", "ECDSA", NULL,
KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
{ "ecdsa-sha2-nistp384", "ECDSA", NULL,
KEY_ECDSA, NID_secp384r1, 0, 0 },
# ifdef OPENSSL_HAS_NISTP521
{ "ecdsa-sha2-nistp521", "ECDSA", NULL,
KEY_ECDSA, NID_secp521r1, 0, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
{ "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
KEY_RSA_CERT, 0, 1, 0 },
{ "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT",
"rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 },
{ "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT",
"rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 },
{ "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL,
KEY_DSA_CERT, 0, 1, 0 },
# ifdef OPENSSL_HAS_ECC
{ "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT", NULL,
KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT", NULL,
KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
# ifdef OPENSSL_HAS_NISTP521
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
{ NULL, NULL, NULL, -1, -1, 0, 0 }
};
const char *
sshkey_type(const struct sshkey *k)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->type == k->type)
return kt->shortname;
}
return "unknown";
}
static const char *
sshkey_ssh_name_from_type_nid(int type, int nid)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
return kt->name;
}
return "ssh-unknown";
}
int
sshkey_type_is_cert(int type)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->type == type)
return kt->cert;
}
return 0;
}
const char *
sshkey_ssh_name(const struct sshkey *k)
{
return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
}
const char *
sshkey_ssh_name_plain(const struct sshkey *k)
{
return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
k->ecdsa_nid);
}
int
sshkey_type_from_name(const char *name)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
/* Only allow shortname matches for plain key types */
if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
(!kt->cert && strcasecmp(kt->shortname, name) == 0))
return kt->type;
}
return KEY_UNSPEC;
}
int
sshkey_ecdsa_nid_from_name(const char *name)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
continue;
if (kt->name != NULL && strcmp(name, kt->name) == 0)
return kt->nid;
}
return -1;
}
char *
sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep)
{
char *tmp, *ret = NULL;
size_t nlen, rlen = 0;
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->name == NULL)
continue;
if (!include_sigonly && kt->sigonly)
continue;
if ((certs_only && !kt->cert) || (plain_only && kt->cert))
continue;
if (ret != NULL)
ret[rlen++] = sep;
nlen = strlen(kt->name);
if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
free(ret);
return NULL;
}
ret = tmp;
memcpy(ret + rlen, kt->name, nlen + 1);
rlen += nlen;
}
return ret;
}
int
sshkey_names_valid2(const char *names, int allow_wildcard)
{
char *s, *cp, *p;
const struct keytype *kt;
int type;
if (names == NULL || strcmp(names, "") == 0)
return 0;
if ((s = cp = strdup(names)) == NULL)
return 0;
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
type = sshkey_type_from_name(p);
if (type == KEY_UNSPEC) {
if (allow_wildcard) {
/*
* Try matching key types against the string.
* If any has a positive or negative match then
* the component is accepted.
*/
for (kt = keytypes; kt->type != -1; kt++) {
if (match_pattern_list(kt->name,
p, 0) != 0)
break;
}
if (kt->type != -1)
continue;
}
free(s);
return 0;
}
}
free(s);
return 1;
}
u_int
sshkey_size(const struct sshkey *k)
{
#ifdef WITH_OPENSSL
const BIGNUM *rsa_n, *dsa_p;
#endif /* WITH_OPENSSL */
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_RSA_CERT:
if (k->rsa == NULL)
return 0;
RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
return BN_num_bits(rsa_n);
case KEY_DSA:
case KEY_DSA_CERT:
if (k->dsa == NULL)
return 0;
DSA_get0_pqg(k->dsa, &dsa_p, NULL, NULL);
return BN_num_bits(dsa_p);
case KEY_ECDSA:
case KEY_ECDSA_CERT:
return sshkey_curve_nid_to_bits(k->ecdsa_nid);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
case KEY_XMSS:
case KEY_XMSS_CERT:
return 256; /* XXX */
}
return 0;
}
static int
sshkey_type_is_valid_ca(int type)
{
switch (type) {
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
case KEY_XMSS:
return 1;
default:
return 0;
}
}
int
sshkey_is_cert(const struct sshkey *k)
{
if (k == NULL)
return 0;
return sshkey_type_is_cert(k->type);
}
/* Return the cert-less equivalent to a certified key type */
int
sshkey_type_plain(int type)
{
switch (type) {
case KEY_RSA_CERT:
return KEY_RSA;
case KEY_DSA_CERT:
return KEY_DSA;
case KEY_ECDSA_CERT:
return KEY_ECDSA;
case KEY_ED25519_CERT:
return KEY_ED25519;
case KEY_XMSS_CERT:
return KEY_XMSS;
default:
return type;
}
}
#ifdef WITH_OPENSSL
/* XXX: these are really begging for a table-driven approach */
int
sshkey_curve_name_to_nid(const char *name)
{
if (strcmp(name, "nistp256") == 0)
return NID_X9_62_prime256v1;
else if (strcmp(name, "nistp384") == 0)
return NID_secp384r1;
# ifdef OPENSSL_HAS_NISTP521
else if (strcmp(name, "nistp521") == 0)
return NID_secp521r1;
# endif /* OPENSSL_HAS_NISTP521 */
else
return -1;
}
u_int
sshkey_curve_nid_to_bits(int nid)
{
switch (nid) {
case NID_X9_62_prime256v1:
return 256;
case NID_secp384r1:
return 384;
# ifdef OPENSSL_HAS_NISTP521
case NID_secp521r1:
return 521;
# endif /* OPENSSL_HAS_NISTP521 */
default:
return 0;
}
}
int
sshkey_ecdsa_bits_to_nid(int bits)
{
switch (bits) {
case 256:
return NID_X9_62_prime256v1;
case 384:
return NID_secp384r1;
# ifdef OPENSSL_HAS_NISTP521
case 521:
return NID_secp521r1;
# endif /* OPENSSL_HAS_NISTP521 */
default:
return -1;
}
}
const char *
sshkey_curve_nid_to_name(int nid)
{
switch (nid) {
case NID_X9_62_prime256v1:
return "nistp256";
case NID_secp384r1:
return "nistp384";
# ifdef OPENSSL_HAS_NISTP521
case NID_secp521r1:
return "nistp521";
# endif /* OPENSSL_HAS_NISTP521 */
default:
return NULL;
}
}
int
sshkey_ec_nid_to_hash_alg(int nid)
{
int kbits = sshkey_curve_nid_to_bits(nid);
if (kbits <= 0)
return -1;
/* RFC5656 section 6.2.1 */
if (kbits <= 256)
return SSH_DIGEST_SHA256;
else if (kbits <= 384)
return SSH_DIGEST_SHA384;
else
return SSH_DIGEST_SHA512;
}
#endif /* WITH_OPENSSL */
static void
cert_free(struct sshkey_cert *cert)
{
u_int i;
if (cert == NULL)
return;
sshbuf_free(cert->certblob);
sshbuf_free(cert->critical);
sshbuf_free(cert->extensions);
free(cert->key_id);
for (i = 0; i < cert->nprincipals; i++)
free(cert->principals[i]);
free(cert->principals);
sshkey_free(cert->signature_key);
free(cert->signature_type);
freezero(cert, sizeof(*cert));
}
static struct sshkey_cert *
cert_new(void)
{
struct sshkey_cert *cert;
if ((cert = calloc(1, sizeof(*cert))) == NULL)
return NULL;
if ((cert->certblob = sshbuf_new()) == NULL ||
(cert->critical = sshbuf_new()) == NULL ||
(cert->extensions = sshbuf_new()) == NULL) {
cert_free(cert);
return NULL;
}
cert->key_id = NULL;
cert->principals = NULL;
cert->signature_key = NULL;
cert->signature_type = NULL;
return cert;
}
struct sshkey *
sshkey_new(int type)
{
struct sshkey *k;
#ifdef WITH_OPENSSL
RSA *rsa;
DSA *dsa;
#endif /* WITH_OPENSSL */
if ((k = calloc(1, sizeof(*k))) == NULL)
return NULL;
k->type = type;
k->ecdsa = NULL;
k->ecdsa_nid = -1;
k->dsa = NULL;
k->rsa = NULL;
k->cert = NULL;
k->ed25519_sk = NULL;
k->ed25519_pk = NULL;
k->xmss_sk = NULL;
k->xmss_pk = NULL;
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_RSA_CERT:
if ((rsa = RSA_new()) == NULL) {
free(k);
return NULL;
}
k->rsa = rsa;
break;
case KEY_DSA:
case KEY_DSA_CERT:
if ((dsa = DSA_new()) == NULL) {
free(k);
return NULL;
}
k->dsa = dsa;
break;
case KEY_ECDSA:
case KEY_ECDSA_CERT:
/* Cannot do anything until we know the group */
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
case KEY_XMSS:
case KEY_XMSS_CERT:
/* no need to prealloc */
break;
case KEY_UNSPEC:
break;
default:
free(k);
return NULL;
}
if (sshkey_is_cert(k)) {
if ((k->cert = cert_new()) == NULL) {
sshkey_free(k);
return NULL;
}
}
return k;
}
void
sshkey_free(struct sshkey *k)
{
if (k == NULL)
return;
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
case KEY_RSA_CERT:
RSA_free(k->rsa);
k->rsa = NULL;
break;
case KEY_DSA:
case KEY_DSA_CERT:
DSA_free(k->dsa);
k->dsa = NULL;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
case KEY_ECDSA_CERT:
EC_KEY_free(k->ecdsa);
k->ecdsa = NULL;
break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
freezero(k->ed25519_pk, ED25519_PK_SZ);
k->ed25519_pk = NULL;
freezero(k->ed25519_sk, ED25519_SK_SZ);
k->ed25519_sk = NULL;
break;
#ifdef WITH_XMSS
case KEY_XMSS:
case KEY_XMSS_CERT:
freezero(k->xmss_pk, sshkey_xmss_pklen(k));
k->xmss_pk = NULL;
freezero(k->xmss_sk, sshkey_xmss_sklen(k));
k->xmss_sk = NULL;
sshkey_xmss_free_state(k);
free(k->xmss_name);
k->xmss_name = NULL;
free(k->xmss_filename);
k->xmss_filename = NULL;
break;
#endif /* WITH_XMSS */
case KEY_UNSPEC:
break;
default:
break;
}
if (sshkey_is_cert(k))
cert_free(k->cert);
freezero(k, sizeof(*k));
}
static int
cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
{
if (a == NULL && b == NULL)
return 1;
if (a == NULL || b == NULL)
return 0;
if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
return 0;
if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
sshbuf_len(a->certblob)) != 0)
return 0;
return 1;
}
/*
* Compare public portions of key only, allowing comparisons between
* certificates and plain keys too.
*/
int
sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
{
#if defined(WITH_OPENSSL)
const BIGNUM *rsa_e_a, *rsa_n_a;
const BIGNUM *rsa_e_b, *rsa_n_b;
const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a;
const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b;
# if defined(OPENSSL_HAS_ECC)
BN_CTX *bnctx;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
if (a == NULL || b == NULL ||
sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
return 0;
switch (a->type) {
#ifdef WITH_OPENSSL
case KEY_RSA_CERT:
case KEY_RSA:
if (a->rsa == NULL || b->rsa == NULL)
return 0;
RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
return BN_cmp(rsa_e_a, rsa_e_b) == 0 &&
BN_cmp(rsa_n_a, rsa_n_b) == 0;
case KEY_DSA_CERT:
case KEY_DSA:
if (a->dsa == NULL || b->dsa == NULL)
return 0;
DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a);
DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b);
DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL);
DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL);
return BN_cmp(dsa_p_a, dsa_p_b) == 0 &&
BN_cmp(dsa_q_a, dsa_q_b) == 0 &&
BN_cmp(dsa_g_a, dsa_g_b) == 0 &&
BN_cmp(dsa_pub_key_a, dsa_pub_key_b) == 0;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
case KEY_ECDSA:
if (a->ecdsa == NULL || b->ecdsa == NULL ||
EC_KEY_get0_public_key(a->ecdsa) == NULL ||
EC_KEY_get0_public_key(b->ecdsa) == NULL)
return 0;
if ((bnctx = BN_CTX_new()) == NULL)
return 0;
if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
EC_KEY_get0_public_key(a->ecdsa),
EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
BN_CTX_free(bnctx);
return 0;
}
BN_CTX_free(bnctx);
return 1;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
#ifdef WITH_XMSS
case KEY_XMSS:
case KEY_XMSS_CERT:
return a->xmss_pk != NULL && b->xmss_pk != NULL &&
sshkey_xmss_pklen(a) == sshkey_xmss_pklen(b) &&
memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) == 0;
#endif /* WITH_XMSS */
default:
return 0;
}
/* NOTREACHED */
}
int
sshkey_equal(const struct sshkey *a, const struct sshkey *b)
{
if (a == NULL || b == NULL || a->type != b->type)
return 0;
if (sshkey_is_cert(a)) {
if (!cert_compare(a->cert, b->cert))
return 0;
}
return sshkey_equal_public(a, b);
}
static int
to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
enum sshkey_serialize_rep opts)
{
int type, ret = SSH_ERR_INTERNAL_ERROR;
const char *typename;
#ifdef WITH_OPENSSL
const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
#endif /* WITH_OPENSSL */
if (key == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (sshkey_is_cert(key)) {
if (key->cert == NULL)
return SSH_ERR_EXPECTED_CERT;
if (sshbuf_len(key->cert->certblob) == 0)
return SSH_ERR_KEY_LACKS_CERTBLOB;
}
type = force_plain ? sshkey_type_plain(key->type) : key->type;
typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
switch (type) {
#ifdef WITH_OPENSSL
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
#ifdef WITH_XMSS
case KEY_XMSS_CERT:
#endif /* WITH_XMSS */
/* Use the existing blob */
/* XXX modified flag? */
if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
return ret;
break;
#ifdef WITH_OPENSSL
case KEY_DSA:
if (key->dsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
DSA_get0_key(key->dsa, &dsa_pub_key, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
(ret = sshbuf_put_bignum2(b, dsa_pub_key)) != 0)
return ret;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
if (key->ecdsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_cstring(b,
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
(ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
return ret;
break;
# endif
case KEY_RSA:
if (key->rsa == NULL)
return SSH_ERR_INVALID_ARGUMENT;
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
(ret = sshbuf_put_bignum2(b, rsa_n)) != 0)
return ret;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
if (key->ed25519_pk == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_string(b,
key->ed25519_pk, ED25519_PK_SZ)) != 0)
return ret;
break;
#ifdef WITH_XMSS
case KEY_XMSS:
if (key->xmss_name == NULL || key->xmss_pk == NULL ||
sshkey_xmss_pklen(key) == 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
(ret = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
(ret = sshbuf_put_string(b,
key->xmss_pk, sshkey_xmss_pklen(key))) != 0 ||
(ret = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0)
return ret;
break;
#endif /* WITH_XMSS */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
return 0;
}
int
sshkey_putb(const struct sshkey *key, struct sshbuf *b)
{
return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT);
}
int
sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b,
enum sshkey_serialize_rep opts)
{
struct sshbuf *tmp;
int r;
if ((tmp = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
r = to_blob_buf(key, tmp, 0, opts);
if (r == 0)
r = sshbuf_put_stringb(b, tmp);
sshbuf_free(tmp);
return r;
}
int
sshkey_puts(const struct sshkey *key, struct sshbuf *b)
{
return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT);
}
int
sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b)
{
return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT);
}
static int
to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain,
enum sshkey_serialize_rep opts)
{
int ret = SSH_ERR_INTERNAL_ERROR;
size_t len;
struct sshbuf *b = NULL;
if (lenp != NULL)
*lenp = 0;
if (blobp != NULL)
*blobp = NULL;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0)
goto out;
len = sshbuf_len(b);
if (lenp != NULL)
*lenp = len;
if (blobp != NULL) {
if ((*blobp = malloc(len)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
memcpy(*blobp, sshbuf_ptr(b), len);
}
ret = 0;
out:
sshbuf_free(b);
return ret;
}
int
sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
{
return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT);
}
int
sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
{
return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT);
}
int
sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
u_char **retp, size_t *lenp)
{
u_char *blob = NULL, *ret = NULL;
size_t blob_len = 0;
int r = SSH_ERR_INTERNAL_ERROR;
if (retp != NULL)
*retp = NULL;
if (lenp != NULL)
*lenp = 0;
if (ssh_digest_bytes(dgst_alg) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT))
!= 0)
goto out;
if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = ssh_digest_memory(dgst_alg, blob, blob_len,
ret, SSH_DIGEST_MAX_LENGTH)) != 0)
goto out;
/* success */
if (retp != NULL) {
*retp = ret;
ret = NULL;
}
if (lenp != NULL)
*lenp = ssh_digest_bytes(dgst_alg);
r = 0;
out:
free(ret);
if (blob != NULL) {
explicit_bzero(blob, blob_len);
free(blob);
}
return r;
}
static char *
fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
{
char *ret;
size_t plen = strlen(alg) + 1;
size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1;
int r;
if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL)
return NULL;
strlcpy(ret, alg, rlen);
strlcat(ret, ":", rlen);
if (dgst_raw_len == 0)
return ret;
if ((r = b64_ntop(dgst_raw, dgst_raw_len,
ret + plen, rlen - plen)) == -1) {
freezero(ret, rlen);
return NULL;
}
/* Trim padding characters from end */
ret[strcspn(ret, "=")] = '\0';
return ret;
}
static char *
fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len)
{
char *retval, hex[5];
size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2;
if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL)
return NULL;
strlcpy(retval, alg, rlen);
strlcat(retval, ":", rlen);
for (i = 0; i < dgst_raw_len; i++) {
snprintf(hex, sizeof(hex), "%s%02x",
i > 0 ? ":" : "", dgst_raw[i]);
strlcat(retval, hex, rlen);
}
return retval;
}
static char *
fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
{
char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
u_int i, j = 0, rounds, seed = 1;
char *retval;
rounds = (dgst_raw_len / 2) + 1;
if ((retval = calloc(rounds, 6)) == NULL)
return NULL;
retval[j++] = 'x';
for (i = 0; i < rounds; i++) {
u_int idx0, idx1, idx2, idx3, idx4;
if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
seed) % 6;
idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
(seed / 6)) % 6;
retval[j++] = vowels[idx0];
retval[j++] = consonants[idx1];
retval[j++] = vowels[idx2];
if ((i + 1) < rounds) {
idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
retval[j++] = consonants[idx3];
retval[j++] = '-';
retval[j++] = consonants[idx4];
seed = ((seed * 5) +
((((u_int)(dgst_raw[2 * i])) * 7) +
((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
}
} else {
idx0 = seed % 6;
idx1 = 16;
idx2 = seed / 6;
retval[j++] = vowels[idx0];
retval[j++] = consonants[idx1];
retval[j++] = vowels[idx2];
}
}
retval[j++] = 'x';
retval[j++] = '\0';
return retval;
}
/*
* Draw an ASCII-Art representing the fingerprint so human brain can
* profit from its built-in pattern recognition ability.
* This technique is called "random art" and can be found in some
* scientific publications like this original paper:
*
* "Hash Visualization: a New Technique to improve Real-World Security",
* Perrig A. and Song D., 1999, International Workshop on Cryptographic
* Techniques and E-Commerce (CrypTEC '99)
* sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
*
* The subject came up in a talk by Dan Kaminsky, too.
*
* If you see the picture is different, the key is different.
* If the picture looks the same, you still know nothing.
*
* The algorithm used here is a worm crawling over a discrete plane,
* leaving a trace (augmenting the field) everywhere it goes.
* Movement is taken from dgst_raw 2bit-wise. Bumping into walls
* makes the respective movement vector be ignored for this turn.
* Graphs are not unambiguous, because circles in graphs can be
* walked in either direction.
*/
/*
* Field sizes for the random art. Have to be odd, so the starting point
* can be in the exact middle of the picture, and FLDBASE should be >=8 .
* Else pictures would be too dense, and drawing the frame would
* fail, too, because the key type would not fit in anymore.
*/
#define FLDBASE 8
#define FLDSIZE_Y (FLDBASE + 1)
#define FLDSIZE_X (FLDBASE * 2 + 1)
static char *
fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
const struct sshkey *k)
{
/*
* Chars to be used after each other every time the worm
* intersects with itself. Matter of taste.
*/
char *augmentation_string = " .o+=*BOX@%&#/^SE";
char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
u_char field[FLDSIZE_X][FLDSIZE_Y];
size_t i, tlen, hlen;
u_int b;
int x, y, r;
size_t len = strlen(augmentation_string) - 1;
if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
return NULL;
/* initialize field */
memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
x = FLDSIZE_X / 2;
y = FLDSIZE_Y / 2;
/* process raw key */
for (i = 0; i < dgst_raw_len; i++) {
int input;
/* each byte conveys four 2-bit move commands */
input = dgst_raw[i];
for (b = 0; b < 4; b++) {
/* evaluate 2 bit, rest is shifted later */
x += (input & 0x1) ? 1 : -1;
y += (input & 0x2) ? 1 : -1;
/* assure we are still in bounds */
x = MAXIMUM(x, 0);
y = MAXIMUM(y, 0);
x = MINIMUM(x, FLDSIZE_X - 1);
y = MINIMUM(y, FLDSIZE_Y - 1);
/* augment the field */
if (field[x][y] < len - 2)
field[x][y]++;
input = input >> 2;
}
}
/* mark starting point and end point*/
field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
field[x][y] = len;
/* assemble title */
r = snprintf(title, sizeof(title), "[%s %u]",
sshkey_type(k), sshkey_size(k));
/* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
if (r < 0 || r > (int)sizeof(title))
r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
tlen = (r <= 0) ? 0 : strlen(title);
/* assemble hash ID. */
r = snprintf(hash, sizeof(hash), "[%s]", alg);
hlen = (r <= 0) ? 0 : strlen(hash);
/* output upper border */
p = retval;
*p++ = '+';
for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
*p++ = '-';
memcpy(p, title, tlen);
p += tlen;
for (i += tlen; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
*p++ = '\n';
/* output content */
for (y = 0; y < FLDSIZE_Y; y++) {
*p++ = '|';
for (x = 0; x < FLDSIZE_X; x++)
*p++ = augmentation_string[MINIMUM(field[x][y], len)];
*p++ = '|';
*p++ = '\n';
}
/* output lower border */
*p++ = '+';
for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
*p++ = '-';
memcpy(p, hash, hlen);
p += hlen;
for (i += hlen; i < FLDSIZE_X; i++)
*p++ = '-';
*p++ = '+';
return retval;
}
char *
sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
enum sshkey_fp_rep dgst_rep)
{
char *retval = NULL;
u_char *dgst_raw;
size_t dgst_raw_len;
if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0)
return NULL;
switch (dgst_rep) {
case SSH_FP_DEFAULT:
if (dgst_alg == SSH_DIGEST_MD5) {
retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
} else {
retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
}
break;
case SSH_FP_HEX:
retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
break;
case SSH_FP_BASE64:
retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len);
break;
case SSH_FP_BUBBLEBABBLE:
retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
break;
case SSH_FP_RANDOMART:
retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg),
dgst_raw, dgst_raw_len, k);
break;
default:
explicit_bzero(dgst_raw, dgst_raw_len);
free(dgst_raw);
return NULL;
}
explicit_bzero(dgst_raw, dgst_raw_len);
free(dgst_raw);
return retval;
}
static int
peek_type_nid(const char *s, size_t l, int *nid)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (kt->name == NULL || strlen(kt->name) != l)
continue;
if (memcmp(s, kt->name, l) == 0) {
*nid = -1;
if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT)
*nid = kt->nid;
return kt->type;
}
}
return KEY_UNSPEC;
}
/* XXX this can now be made const char * */
int
sshkey_read(struct sshkey *ret, char **cpp)
{
struct sshkey *k;
char *cp, *blobcopy;
size_t space;
int r, type, curve_nid = -1;
struct sshbuf *blob;
if (ret == NULL)
return SSH_ERR_INVALID_ARGUMENT;
switch (ret->type) {
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA:
case KEY_ECDSA:
case KEY_ED25519:
case KEY_DSA_CERT:
case KEY_ECDSA_CERT:
case KEY_RSA_CERT:
case KEY_ED25519_CERT:
#ifdef WITH_XMSS
case KEY_XMSS:
case KEY_XMSS_CERT:
#endif /* WITH_XMSS */
break; /* ok */
default:
return SSH_ERR_INVALID_ARGUMENT;
}
/* Decode type */
cp = *cpp;
space = strcspn(cp, " \t");
if (space == strlen(cp))
return SSH_ERR_INVALID_FORMAT;
if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC)
return SSH_ERR_INVALID_FORMAT;
/* skip whitespace */
for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
;
if (*cp == '\0')
return SSH_ERR_INVALID_FORMAT;
if (ret->type != KEY_UNSPEC && ret->type != type)
return SSH_ERR_KEY_TYPE_MISMATCH;
if ((blob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
/* find end of keyblob and decode */
space = strcspn(cp, " \t");
if ((blobcopy = strndup(cp, space)) == NULL) {
sshbuf_free(blob);
return SSH_ERR_ALLOC_FAIL;
}
if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) {
free(blobcopy);
sshbuf_free(blob);
return r;
}
free(blobcopy);
if ((r = sshkey_fromb(blob, &k)) != 0) {
sshbuf_free(blob);
return r;
}
sshbuf_free(blob);
/* skip whitespace and leave cp at start of comment */
for (cp += space; *cp == ' ' || *cp == '\t'; cp++)
;
/* ensure type of blob matches type at start of line */
if (k->type != type) {
sshkey_free(k);
return SSH_ERR_KEY_TYPE_MISMATCH;
}
if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) {
sshkey_free(k);
return SSH_ERR_EC_CURVE_MISMATCH;
}
/* Fill in ret from parsed key */
ret->type = type;
if (sshkey_is_cert(ret)) {
if (!sshkey_is_cert(k)) {
sshkey_free(k);
return SSH_ERR_EXPECTED_CERT;
}
if (ret->cert != NULL)
cert_free(ret->cert);
ret->cert = k->cert;
k->cert = NULL;
}
switch (sshkey_type_plain(ret->type)) {
#ifdef WITH_OPENSSL
case KEY_RSA:
RSA_free(ret->rsa);
ret->rsa = k->rsa;
k->rsa = NULL;
#ifdef DEBUG_PK
RSA_print_fp(stderr, ret->rsa, 8);
#endif
break;
case KEY_DSA:
DSA_free(ret->dsa);
ret->dsa = k->dsa;
k->dsa = NULL;
#ifdef DEBUG_PK
DSA_print_fp(stderr, ret->dsa, 8);
#endif
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
EC_KEY_free(ret->ecdsa);
ret->ecdsa = k->ecdsa;
ret->ecdsa_nid = k->ecdsa_nid;
k->ecdsa = NULL;
k->ecdsa_nid = -1;
#ifdef DEBUG_PK
sshkey_dump_ec_key(ret->ecdsa);
#endif
break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
freezero(ret->ed25519_pk, ED25519_PK_SZ);
ret->ed25519_pk = k->ed25519_pk;
k->ed25519_pk = NULL;
#ifdef DEBUG_PK
/* XXX */
#endif
break;
#ifdef WITH_XMSS
case KEY_XMSS:
free(ret->xmss_pk);
ret->xmss_pk = k->xmss_pk;
k->xmss_pk = NULL;
free(ret->xmss_state);
ret->xmss_state = k->xmss_state;
k->xmss_state = NULL;
free(ret->xmss_name);
ret->xmss_name = k->xmss_name;
k->xmss_name = NULL;
free(ret->xmss_filename);
ret->xmss_filename = k->xmss_filename;
k->xmss_filename = NULL;
#ifdef DEBUG_PK
/* XXX */
#endif
break;
#endif /* WITH_XMSS */
default:
sshkey_free(k);
return SSH_ERR_INTERNAL_ERROR;
}
sshkey_free(k);
/* success */
*cpp = cp;
return 0;
}
int
sshkey_to_base64(const struct sshkey *key, char **b64p)
{
int r = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL;
char *uu = NULL;
if (b64p != NULL)
*b64p = NULL;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_putb(key, b)) != 0)
goto out;
if ((uu = sshbuf_dtob64(b)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* Success */
if (b64p != NULL) {
*b64p = uu;
uu = NULL;
}
r = 0;
out:
sshbuf_free(b);
free(uu);
return r;
}
int
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
{
int r = SSH_ERR_INTERNAL_ERROR;
char *uu = NULL;
if ((r = sshkey_to_base64(key, &uu)) != 0)
goto out;
if ((r = sshbuf_putf(b, "%s %s",
sshkey_ssh_name(key), uu)) != 0)
goto out;
r = 0;
out:
free(uu);
return r;
}
int
sshkey_write(const struct sshkey *key, FILE *f)
{
struct sshbuf *b = NULL;
int r = SSH_ERR_INTERNAL_ERROR;
if ((b = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_format_text(key, b)) != 0)
goto out;
if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
if (feof(f))
errno = EPIPE;
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
/* Success */
r = 0;
out:
sshbuf_free(b);
return r;
}
const char *
sshkey_cert_type(const struct sshkey *k)
{
switch (k->cert->type) {
case SSH2_CERT_TYPE_USER:
return "user";
case SSH2_CERT_TYPE_HOST:
return "host";
default:
return "unknown";
}
}
#ifdef WITH_OPENSSL
static int
rsa_generate_private_key(u_int bits, RSA **rsap)
{
RSA *private = NULL;
BIGNUM *f4 = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
if (rsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
bits > SSHBUF_MAX_BIGNUM * 8)
return SSH_ERR_KEY_LENGTH;
*rsap = NULL;
if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (!BN_set_word(f4, RSA_F4) ||
!RSA_generate_key_ex(private, bits, f4, NULL)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
*rsap = private;
private = NULL;
ret = 0;
out:
RSA_free(private);
BN_free(f4);
return ret;
}
static int
dsa_generate_private_key(u_int bits, DSA **dsap)
{
DSA *private;
int ret = SSH_ERR_INTERNAL_ERROR;
if (dsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (bits != 1024)
return SSH_ERR_KEY_LENGTH;
if ((private = DSA_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
*dsap = NULL;
if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
NULL, NULL) || !DSA_generate_key(private)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
*dsap = private;
private = NULL;
ret = 0;
out:
DSA_free(private);
return ret;
}
# ifdef OPENSSL_HAS_ECC
int
sshkey_ecdsa_key_to_nid(EC_KEY *k)
{
EC_GROUP *eg;
int nids[] = {
NID_X9_62_prime256v1,
NID_secp384r1,
# ifdef OPENSSL_HAS_NISTP521
NID_secp521r1,
# endif /* OPENSSL_HAS_NISTP521 */
-1
};
int nid;
u_int i;
BN_CTX *bnctx;
const EC_GROUP *g = EC_KEY_get0_group(k);
/*
* The group may be stored in a ASN.1 encoded private key in one of two
* ways: as a "named group", which is reconstituted by ASN.1 object ID
* or explicit group parameters encoded into the key blob. Only the
* "named group" case sets the group NID for us, but we can figure
* it out for the other case by comparing against all the groups that
* are supported.
*/
if ((nid = EC_GROUP_get_curve_name(g)) > 0)
return nid;
if ((bnctx = BN_CTX_new()) == NULL)
return -1;
for (i = 0; nids[i] != -1; i++) {
if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
BN_CTX_free(bnctx);
return -1;
}
if (EC_GROUP_cmp(g, eg, bnctx) == 0)
break;
EC_GROUP_free(eg);
}
BN_CTX_free(bnctx);
if (nids[i] != -1) {
/* Use the group with the NID attached */
EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
if (EC_KEY_set_group(k, eg) != 1) {
EC_GROUP_free(eg);
return -1;
}
}
return nids[i];
}
static int
ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
{
EC_KEY *private;
int ret = SSH_ERR_INTERNAL_ERROR;
if (nid == NULL || ecdsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
return SSH_ERR_KEY_LENGTH;
*ecdsap = NULL;
if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (EC_KEY_generate_key(private) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
*ecdsap = private;
private = NULL;
ret = 0;
out:
EC_KEY_free(private);
return ret;
}
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
int
sshkey_generate(int type, u_int bits, struct sshkey **keyp)
{
struct sshkey *k;
int ret = SSH_ERR_INTERNAL_ERROR;
if (keyp == NULL)
return SSH_ERR_INVALID_ARGUMENT;
*keyp = NULL;
if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
return SSH_ERR_ALLOC_FAIL;
switch (type) {
case KEY_ED25519:
if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
(k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
break;
}
crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
ret = 0;
break;
#ifdef WITH_XMSS
case KEY_XMSS:
ret = sshkey_xmss_generate_private_key(k, bits);
break;
#endif /* WITH_XMSS */
#ifdef WITH_OPENSSL
case KEY_DSA:
ret = dsa_generate_private_key(bits, &k->dsa);
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
&k->ecdsa);
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
ret = rsa_generate_private_key(bits, &k->rsa);
break;
#endif /* WITH_OPENSSL */
default:
ret = SSH_ERR_INVALID_ARGUMENT;
}
if (ret == 0) {
k->type = type;
*keyp = k;
} else
sshkey_free(k);
return ret;
}
int
sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
{
u_int i;
const struct sshkey_cert *from;
struct sshkey_cert *to;
int r = SSH_ERR_INTERNAL_ERROR;
if (to_key == NULL || (from = from_key->cert) == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((to = cert_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
(r = sshbuf_putb(to->critical, from->critical)) != 0 ||
(r = sshbuf_putb(to->extensions, from->extensions)) != 0)
goto out;
to->serial = from->serial;
to->type = from->type;
if (from->key_id == NULL)
to->key_id = NULL;
else if ((to->key_id = strdup(from->key_id)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
to->valid_after = from->valid_after;
to->valid_before = from->valid_before;
if (from->signature_key == NULL)
to->signature_key = NULL;
else if ((r = sshkey_from_private(from->signature_key,
&to->signature_key)) != 0)
goto out;
if (from->signature_type != NULL &&
(to->signature_type = strdup(from->signature_type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if (from->nprincipals > 0) {
if ((to->principals = calloc(from->nprincipals,
sizeof(*to->principals))) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
for (i = 0; i < from->nprincipals; i++) {
to->principals[i] = strdup(from->principals[i]);
if (to->principals[i] == NULL) {
to->nprincipals = i;
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
}
}
to->nprincipals = from->nprincipals;
/* success */
cert_free(to_key->cert);
to_key->cert = to;
to = NULL;
r = 0;
out:
cert_free(to);
return r;
}
int
sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
{
struct sshkey *n = NULL;
int r = SSH_ERR_INTERNAL_ERROR;
#ifdef WITH_OPENSSL
const BIGNUM *rsa_n, *rsa_e;
BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL;
BIGNUM *dsa_pub_key_dup = NULL;
#endif /* WITH_OPENSSL */
*pkp = NULL;
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_DSA_CERT:
if ((n = sshkey_new(k->type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
if ((dsa_p_dup = BN_dup(dsa_p)) == NULL ||
(dsa_q_dup = BN_dup(dsa_q)) == NULL ||
(dsa_g_dup = BN_dup(dsa_g)) == NULL ||
(dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (!DSA_set0_pqg(n->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */
if (!DSA_set0_key(n->dsa, dsa_pub_key_dup, NULL)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_pub_key_dup = NULL; /* transferred */
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
case KEY_ECDSA_CERT:
if ((n = sshkey_new(k->type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
n->ecdsa_nid = k->ecdsa_nid;
n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
if (n->ecdsa == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (EC_KEY_set_public_key(n->ecdsa,
EC_KEY_get0_public_key(k->ecdsa)) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
case KEY_RSA_CERT:
if ((n = sshkey_new(k->type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
(rsa_e_dup = BN_dup(rsa_e)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (!RSA_set0_key(n->rsa, rsa_n_dup, rsa_e_dup, NULL)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_n_dup = rsa_e_dup = NULL; /* transferred */
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
if ((n = sshkey_new(k->type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (k->ed25519_pk != NULL) {
if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
}
break;
#ifdef WITH_XMSS
case KEY_XMSS:
case KEY_XMSS_CERT:
if ((n = sshkey_new(k->type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshkey_xmss_init(n, k->xmss_name)) != 0)
goto out;
if (k->xmss_pk != NULL) {
size_t pklen = sshkey_xmss_pklen(k);
if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
}
if ((n->xmss_pk = malloc(pklen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
memcpy(n->xmss_pk, k->xmss_pk, pklen);
}
break;
#endif /* WITH_XMSS */
default:
r = SSH_ERR_KEY_TYPE_UNKNOWN;
goto out;
}
if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0)
goto out;
/* success */
*pkp = n;
n = NULL;
r = 0;
out:
sshkey_free(n);
#ifdef WITH_OPENSSL
BN_clear_free(rsa_n_dup);
BN_clear_free(rsa_e_dup);
BN_clear_free(dsa_p_dup);
BN_clear_free(dsa_q_dup);
BN_clear_free(dsa_g_dup);
BN_clear_free(dsa_pub_key_dup);
#endif
return r;
}
static int
cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
{
struct sshbuf *principals = NULL, *crit = NULL;
struct sshbuf *exts = NULL, *ca = NULL;
u_char *sig = NULL;
size_t signed_len = 0, slen = 0, kidlen = 0;
int ret = SSH_ERR_INTERNAL_ERROR;
/* Copy the entire key blob for verification and later serialisation */
if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0)
return ret;
/* Parse body of certificate up to signature */
if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 ||
(ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
(ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
(ret = sshbuf_froms(b, &principals)) != 0 ||
(ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
(ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
(ret = sshbuf_froms(b, &crit)) != 0 ||
(ret = sshbuf_froms(b, &exts)) != 0 ||
(ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
(ret = sshbuf_froms(b, &ca)) != 0) {
/* XXX debug print error for ret */
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* Signature is left in the buffer so we can calculate this length */
signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (key->cert->type != SSH2_CERT_TYPE_USER &&
key->cert->type != SSH2_CERT_TYPE_HOST) {
ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
goto out;
}
/* Parse principals section */
while (sshbuf_len(principals) > 0) {
char *principal = NULL;
char **oprincipals = NULL;
if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((ret = sshbuf_get_cstring(principals, &principal,
NULL)) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
oprincipals = key->cert->principals;
key->cert->principals = recallocarray(key->cert->principals,
key->cert->nprincipals, key->cert->nprincipals + 1,
sizeof(*key->cert->principals));
if (key->cert->principals == NULL) {
free(principal);
key->cert->principals = oprincipals;
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
key->cert->principals[key->cert->nprincipals++] = principal;
}
/*
* Stash a copies of the critical options and extensions sections
* for later use.
*/
if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 ||
(exts != NULL &&
(ret = sshbuf_putb(key->cert->extensions, exts)) != 0))
goto out;
/*
* Validate critical options and extensions sections format.
*/
while (sshbuf_len(crit) != 0) {
if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 ||
(ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) {
sshbuf_reset(key->cert->critical);
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
}
while (exts != NULL && sshbuf_len(exts) != 0) {
if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 ||
(ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) {
sshbuf_reset(key->cert->extensions);
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
}
/* Parse CA key and check signature */
if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) {
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
goto out;
}
if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
goto out;
}
if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0)
goto out;
if ((ret = get_sigtype(sig, slen, &key->cert->signature_type)) != 0)
goto out;
/* Success */
ret = 0;
out:
sshbuf_free(ca);
sshbuf_free(crit);
sshbuf_free(exts);
sshbuf_free(principals);
free(sig);
return ret;
}
#ifdef WITH_OPENSSL
static int
check_rsa_length(const RSA *rsa)
{
const BIGNUM *rsa_n;
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
return SSH_ERR_KEY_LENGTH;
return 0;
}
#endif
static int
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
int allow_cert)
{
int type, ret = SSH_ERR_INTERNAL_ERROR;
char *ktype = NULL, *curve = NULL, *xmss_name = NULL;
struct sshkey *key = NULL;
size_t len;
u_char *pk = NULL;
struct sshbuf *copy;
#if defined(WITH_OPENSSL)
BIGNUM *rsa_n = NULL, *rsa_e = NULL;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
# if defined(OPENSSL_HAS_ECC)
EC_POINT *q = NULL;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
#ifdef DEBUG_PK /* XXX */
sshbuf_dump(b, stderr);
#endif
if (keyp != NULL)
*keyp = NULL;
if ((copy = sshbuf_fromb(b)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
type = sshkey_type_from_name(ktype);
if (!allow_cert && sshkey_type_is_cert(type)) {
ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
goto out;
}
switch (type) {
#ifdef WITH_OPENSSL
case KEY_RSA_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* FALLTHROUGH */
case KEY_RSA:
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((rsa_e = BN_new()) == NULL ||
- (rsa_n = BN_new()) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (sshbuf_get_bignum2(b, rsa_e) != 0 ||
- sshbuf_get_bignum2(b, rsa_n) != 0) {
+ if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
+ sshbuf_get_bignum2(b, &rsa_n) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_n = rsa_e = NULL; /* transferred */
if ((ret = check_rsa_length(key->rsa)) != 0)
goto out;
#ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8);
#endif
break;
case KEY_DSA_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* FALLTHROUGH */
case KEY_DSA:
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((dsa_p = BN_new()) == NULL ||
- (dsa_q = BN_new()) == NULL ||
- (dsa_g = BN_new()) == NULL ||
- (dsa_pub_key = BN_new()) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (sshbuf_get_bignum2(b, dsa_p) != 0 ||
- sshbuf_get_bignum2(b, dsa_q) != 0 ||
- sshbuf_get_bignum2(b, dsa_g) != 0 ||
- sshbuf_get_bignum2(b, dsa_pub_key) != 0) {
+ if (sshbuf_get_bignum2(b, &dsa_p) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_q) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_g) != 0 ||
+ sshbuf_get_bignum2(b, &dsa_pub_key) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_p = dsa_q = dsa_g = NULL; /* transferred */
if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_pub_key = NULL; /* transferred */
#ifdef DEBUG_PK
DSA_print_fp(stderr, key->dsa, 8);
#endif
break;
case KEY_ECDSA_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* FALLTHROUGH */
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
key->ecdsa_nid = sshkey_ecdsa_nid_from_name(ktype);
if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
ret = SSH_ERR_EC_CURVE_MISMATCH;
goto out;
}
EC_KEY_free(key->ecdsa);
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
== NULL) {
ret = SSH_ERR_EC_CURVE_INVALID;
goto out;
}
if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
q) != 0) {
ret = SSH_ERR_KEY_INVALID_EC_VALUE;
goto out;
}
if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
/* XXX assume it is a allocation error */
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
#ifdef DEBUG_PK
sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
#endif
break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* FALLTHROUGH */
case KEY_ED25519:
if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
goto out;
if (len != ED25519_PK_SZ) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
key->ed25519_pk = pk;
pk = NULL;
break;
#ifdef WITH_XMSS
case KEY_XMSS_CERT:
/* Skip nonce */
if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* FALLTHROUGH */
case KEY_XMSS:
if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0)
goto out;
if ((key = sshkey_new(type)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((ret = sshkey_xmss_init(key, xmss_name)) != 0)
goto out;
if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
goto out;
if (len == 0 || len != sshkey_xmss_pklen(key)) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
key->xmss_pk = pk;
pk = NULL;
if (type != KEY_XMSS_CERT &&
(ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0)
goto out;
break;
#endif /* WITH_XMSS */
case KEY_UNSPEC:
default:
ret = SSH_ERR_KEY_TYPE_UNKNOWN;
goto out;
}
/* Parse certificate potion */
if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0)
goto out;
if (key != NULL && sshbuf_len(b) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
ret = 0;
if (keyp != NULL) {
*keyp = key;
key = NULL;
}
out:
sshbuf_free(copy);
sshkey_free(key);
free(xmss_name);
free(ktype);
free(curve);
free(pk);
#if defined(WITH_OPENSSL)
BN_clear_free(rsa_n);
BN_clear_free(rsa_e);
BN_clear_free(dsa_p);
BN_clear_free(dsa_q);
BN_clear_free(dsa_g);
BN_clear_free(dsa_pub_key);
# if defined(OPENSSL_HAS_ECC)
EC_POINT_free(q);
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
return ret;
}
int
sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
{
struct sshbuf *b;
int r;
if ((b = sshbuf_from(blob, blen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
r = sshkey_from_blob_internal(b, keyp, 1);
sshbuf_free(b);
return r;
}
int
sshkey_fromb(struct sshbuf *b, struct sshkey **keyp)
{
return sshkey_from_blob_internal(b, keyp, 1);
}
int
sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
{
struct sshbuf *b;
int r;
if ((r = sshbuf_froms(buf, &b)) != 0)
return r;
r = sshkey_from_blob_internal(b, keyp, 1);
sshbuf_free(b);
return r;
}
static int
get_sigtype(const u_char *sig, size_t siglen, char **sigtypep)
{
int r;
struct sshbuf *b = NULL;
char *sigtype = NULL;
if (sigtypep != NULL)
*sigtypep = NULL;
if ((b = sshbuf_from(sig, siglen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0)
goto out;
/* success */
if (sigtypep != NULL) {
*sigtypep = sigtype;
sigtype = NULL;
}
r = 0;
out:
free(sigtype);
sshbuf_free(b);
return r;
}
/*
*
* Checks whether a certificate's signature type is allowed.
* Returns 0 (success) if the certificate signature type appears in the
* "allowed" pattern-list, or the key is not a certificate to begin with.
* Otherwise returns a ssherr.h code.
*/
int
sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed)
{
if (key == NULL || allowed == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (!sshkey_type_is_cert(key->type))
return 0;
if (key->cert == NULL || key->cert->signature_type == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1)
return SSH_ERR_SIGN_ALG_UNSUPPORTED;
return 0;
}
/*
* Returns the expected signature algorithm for a given public key algorithm.
*/
const char *
sshkey_sigalg_by_name(const char *name)
{
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
if (strcmp(kt->name, name) != 0)
continue;
if (kt->sigalg != NULL)
return kt->sigalg;
if (!kt->cert)
return kt->name;
return sshkey_ssh_name_from_type_nid(
sshkey_type_plain(kt->type), kt->nid);
}
return NULL;
}
/*
* Verifies that the signature algorithm appearing inside the signature blob
* matches that which was requested.
*/
int
sshkey_check_sigtype(const u_char *sig, size_t siglen,
const char *requested_alg)
{
const char *expected_alg;
char *sigtype = NULL;
int r;
if (requested_alg == NULL)
return 0;
if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((r = get_sigtype(sig, siglen, &sigtype)) != 0)
return r;
r = strcmp(expected_alg, sigtype) == 0;
free(sigtype);
return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED;
}
int
sshkey_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *alg, u_int compat)
{
if (sigp != NULL)
*sigp = NULL;
if (lenp != NULL)
*lenp = 0;
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_DSA_CERT:
case KEY_DSA:
return ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
case KEY_ECDSA:
return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA_CERT:
case KEY_RSA:
return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
#ifdef WITH_XMSS
case KEY_XMSS:
case KEY_XMSS_CERT:
return ssh_xmss_sign(key, sigp, lenp, data, datalen, compat);
#endif /* WITH_XMSS */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
}
/*
* ssh_key_verify returns 0 for a correct signature and < 0 on error.
* If "alg" specified, then the signature must use that algorithm.
*/
int
sshkey_verify(const struct sshkey *key,
const u_char *sig, size_t siglen,
const u_char *data, size_t dlen, const char *alg, u_int compat)
{
if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
return SSH_ERR_INVALID_ARGUMENT;
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_DSA_CERT:
case KEY_DSA:
return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
case KEY_ECDSA:
return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA_CERT:
case KEY_RSA:
return ssh_rsa_verify(key, sig, siglen, data, dlen, alg);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
#ifdef WITH_XMSS
case KEY_XMSS:
case KEY_XMSS_CERT:
return ssh_xmss_verify(key, sig, siglen, data, dlen, compat);
#endif /* WITH_XMSS */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
}
/* Convert a plain key to their _CERT equivalent */
int
sshkey_to_certified(struct sshkey *k)
{
int newtype;
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
newtype = KEY_RSA_CERT;
break;
case KEY_DSA:
newtype = KEY_DSA_CERT;
break;
case KEY_ECDSA:
newtype = KEY_ECDSA_CERT;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
newtype = KEY_ED25519_CERT;
break;
#ifdef WITH_XMSS
case KEY_XMSS:
newtype = KEY_XMSS_CERT;
break;
#endif /* WITH_XMSS */
default:
return SSH_ERR_INVALID_ARGUMENT;
}
if ((k->cert = cert_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
k->type = newtype;
return 0;
}
/* Convert a certificate to its raw key equivalent */
int
sshkey_drop_cert(struct sshkey *k)
{
if (!sshkey_type_is_cert(k->type))
return SSH_ERR_KEY_TYPE_UNKNOWN;
cert_free(k->cert);
k->cert = NULL;
k->type = sshkey_type_plain(k->type);
return 0;
}
/* Sign a certified key, (re-)generating the signed certblob. */
int
sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
sshkey_certify_signer *signer, void *signer_ctx)
{
struct sshbuf *principals = NULL;
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
size_t i, ca_len, sig_len;
int ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *cert = NULL;
char *sigtype = NULL;
#ifdef WITH_OPENSSL
const BIGNUM *rsa_n, *rsa_e, *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key;
#endif /* WITH_OPENSSL */
if (k == NULL || k->cert == NULL ||
k->cert->certblob == NULL || ca == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (!sshkey_is_cert(k))
return SSH_ERR_KEY_TYPE_UNKNOWN;
if (!sshkey_type_is_valid_ca(ca->type))
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
/*
* If no alg specified as argument but a signature_type was set,
* then prefer that. If both were specified, then they must match.
*/
if (alg == NULL)
alg = k->cert->signature_type;
else if (k->cert->signature_type != NULL &&
strcmp(alg, k->cert->signature_type) != 0)
return SSH_ERR_INVALID_ARGUMENT;
if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
cert = k->cert->certblob; /* for readability */
sshbuf_reset(cert);
if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
goto out;
/* -v01 certs put nonce first */
arc4random_buf(&nonce, sizeof(nonce));
if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
goto out;
/* XXX this substantially duplicates to_blob(); refactor */
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_DSA_CERT:
DSA_get0_pqg(k->dsa, &dsa_p, &dsa_q, &dsa_g);
DSA_get0_key(k->dsa, &dsa_pub_key, NULL);
if ((ret = sshbuf_put_bignum2(cert, dsa_p)) != 0 ||
(ret = sshbuf_put_bignum2(cert, dsa_q)) != 0 ||
(ret = sshbuf_put_bignum2(cert, dsa_g)) != 0 ||
(ret = sshbuf_put_bignum2(cert, dsa_pub_key)) != 0)
goto out;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA_CERT:
if ((ret = sshbuf_put_cstring(cert,
sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
(ret = sshbuf_put_ec(cert,
EC_KEY_get0_public_key(k->ecdsa),
EC_KEY_get0_group(k->ecdsa))) != 0)
goto out;
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA_CERT:
RSA_get0_key(k->rsa, &rsa_n, &rsa_e, NULL);
if ((ret = sshbuf_put_bignum2(cert, rsa_e)) != 0 ||
(ret = sshbuf_put_bignum2(cert, rsa_n)) != 0)
goto out;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519_CERT:
if ((ret = sshbuf_put_string(cert,
k->ed25519_pk, ED25519_PK_SZ)) != 0)
goto out;
break;
#ifdef WITH_XMSS
case KEY_XMSS_CERT:
if (k->xmss_name == NULL) {
ret = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((ret = sshbuf_put_cstring(cert, k->xmss_name)) ||
(ret = sshbuf_put_string(cert,
k->xmss_pk, sshkey_xmss_pklen(k))) != 0)
goto out;
break;
#endif /* WITH_XMSS */
default:
ret = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 ||
(ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
(ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
goto out;
if ((principals = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
for (i = 0; i < k->cert->nprincipals; i++) {
if ((ret = sshbuf_put_cstring(principals,
k->cert->principals[i])) != 0)
goto out;
}
if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
(ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
(ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
(ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 ||
(ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 ||
(ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
(ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
goto out;
/* Sign the whole mess */
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
goto out;
/* Check and update signature_type against what was actually used */
if ((ret = get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
goto out;
if (alg != NULL && strcmp(alg, sigtype) != 0) {
ret = SSH_ERR_SIGN_ALG_UNSUPPORTED;
goto out;
}
if (k->cert->signature_type == NULL) {
k->cert->signature_type = sigtype;
sigtype = NULL;
}
/* Append signature and we are done */
if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
goto out;
ret = 0;
out:
if (ret != 0)
sshbuf_reset(cert);
free(sig_blob);
free(ca_blob);
free(sigtype);
sshbuf_free(principals);
return ret;
}
static int
default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen,
const char *alg, u_int compat, void *ctx)
{
if (ctx != NULL)
return SSH_ERR_INVALID_ARGUMENT;
return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat);
}
int
sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
{
return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL);
}
int
sshkey_cert_check_authority(const struct sshkey *k,
int want_host, int require_principal,
const char *name, const char **reason)
{
u_int i, principal_matches;
time_t now = time(NULL);
if (reason != NULL)
*reason = NULL;
if (want_host) {
if (k->cert->type != SSH2_CERT_TYPE_HOST) {
*reason = "Certificate invalid: not a host certificate";
return SSH_ERR_KEY_CERT_INVALID;
}
} else {
if (k->cert->type != SSH2_CERT_TYPE_USER) {
*reason = "Certificate invalid: not a user certificate";
return SSH_ERR_KEY_CERT_INVALID;
}
}
if (now < 0) {
/* yikes - system clock before epoch! */
*reason = "Certificate invalid: not yet valid";
return SSH_ERR_KEY_CERT_INVALID;
}
if ((u_int64_t)now < k->cert->valid_after) {
*reason = "Certificate invalid: not yet valid";
return SSH_ERR_KEY_CERT_INVALID;
}
if ((u_int64_t)now >= k->cert->valid_before) {
*reason = "Certificate invalid: expired";
return SSH_ERR_KEY_CERT_INVALID;
}
if (k->cert->nprincipals == 0) {
if (require_principal) {
*reason = "Certificate lacks principal list";
return SSH_ERR_KEY_CERT_INVALID;
}
} else if (name != NULL) {
principal_matches = 0;
for (i = 0; i < k->cert->nprincipals; i++) {
if (strcmp(name, k->cert->principals[i]) == 0) {
principal_matches = 1;
break;
}
}
if (!principal_matches) {
*reason = "Certificate invalid: name is not a listed "
"principal";
return SSH_ERR_KEY_CERT_INVALID;
}
}
return 0;
}
size_t
sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
{
char from[32], to[32], ret[64];
time_t tt;
struct tm *tm;
*from = *to = '\0';
if (cert->valid_after == 0 &&
cert->valid_before == 0xffffffffffffffffULL)
return strlcpy(s, "forever", l);
if (cert->valid_after != 0) {
/* XXX revisit INT_MAX in 2038 :) */
tt = cert->valid_after > INT_MAX ?
INT_MAX : cert->valid_after;
tm = localtime(&tt);
strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
}
if (cert->valid_before != 0xffffffffffffffffULL) {
/* XXX revisit INT_MAX in 2038 :) */
tt = cert->valid_before > INT_MAX ?
INT_MAX : cert->valid_before;
tm = localtime(&tt);
strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
}
if (cert->valid_after == 0)
snprintf(ret, sizeof(ret), "before %s", to);
else if (cert->valid_before == 0xffffffffffffffffULL)
snprintf(ret, sizeof(ret), "after %s", from);
else
snprintf(ret, sizeof(ret), "from %s to %s", from, to);
return strlcpy(s, ret, l);
}
int
sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
enum sshkey_serialize_rep opts)
{
int r = SSH_ERR_INTERNAL_ERROR;
#ifdef WITH_OPENSSL
const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dsa_priv_key;
#endif /* WITH_OPENSSL */
if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
goto out;
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_RSA:
RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_q)) != 0)
goto out;
break;
case KEY_RSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
(r = sshbuf_put_bignum2(b, rsa_q)) != 0)
goto out;
break;
case KEY_DSA:
DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g);
DSA_get0_key(key->dsa, &dsa_pub_key, &dsa_priv_key);
if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_q)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_g)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
goto out;
break;
case KEY_DSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
DSA_get0_key(key->dsa, NULL, &dsa_priv_key);
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0)
goto out;
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
if ((r = sshbuf_put_cstring(b,
sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
(r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
(r = sshbuf_put_bignum2(b,
EC_KEY_get0_private_key(key->ecdsa))) != 0)
goto out;
break;
case KEY_ECDSA_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_bignum2(b,
EC_KEY_get0_private_key(key->ecdsa))) != 0)
goto out;
break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
if ((r = sshbuf_put_string(b, key->ed25519_pk,
ED25519_PK_SZ)) != 0 ||
(r = sshbuf_put_string(b, key->ed25519_sk,
ED25519_SK_SZ)) != 0)
goto out;
break;
case KEY_ED25519_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_string(b, key->ed25519_pk,
ED25519_PK_SZ)) != 0 ||
(r = sshbuf_put_string(b, key->ed25519_sk,
ED25519_SK_SZ)) != 0)
goto out;
break;
#ifdef WITH_XMSS
case KEY_XMSS:
if (key->xmss_name == NULL) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
(r = sshbuf_put_string(b, key->xmss_pk,
sshkey_xmss_pklen(key))) != 0 ||
(r = sshbuf_put_string(b, key->xmss_sk,
sshkey_xmss_sklen(key))) != 0 ||
(r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
goto out;
break;
case KEY_XMSS_CERT:
if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0 ||
key->xmss_name == NULL) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
(r = sshbuf_put_cstring(b, key->xmss_name)) != 0 ||
(r = sshbuf_put_string(b, key->xmss_pk,
sshkey_xmss_pklen(key))) != 0 ||
(r = sshbuf_put_string(b, key->xmss_sk,
sshkey_xmss_sklen(key))) != 0 ||
(r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0)
goto out;
break;
#endif /* WITH_XMSS */
default:
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
/* success */
r = 0;
out:
return r;
}
int
sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
{
return sshkey_private_serialize_opt(key, b,
SSHKEY_SERIALIZE_DEFAULT);
}
int
sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
{
char *tname = NULL, *curve = NULL, *xmss_name = NULL;
struct sshkey *k = NULL;
size_t pklen = 0, sklen = 0;
int type, r = SSH_ERR_INTERNAL_ERROR;
u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
u_char *xmss_pk = NULL, *xmss_sk = NULL;
#ifdef WITH_OPENSSL
BIGNUM *exponent = NULL;
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
#endif /* WITH_OPENSSL */
if (kp != NULL)
*kp = NULL;
if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
goto out;
type = sshkey_type_from_name(tname);
switch (type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((dsa_p = BN_new()) == NULL ||
- (dsa_q = BN_new()) == NULL ||
- (dsa_g = BN_new()) == NULL ||
- (dsa_pub_key = BN_new()) == NULL ||
- (dsa_priv_key = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshbuf_get_bignum2(buf, dsa_p)) != 0 ||
- (r = sshbuf_get_bignum2(buf, dsa_q)) != 0 ||
- (r = sshbuf_get_bignum2(buf, dsa_g)) != 0 ||
- (r = sshbuf_get_bignum2(buf, dsa_pub_key)) != 0 ||
- (r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0)
+ if ((r = sshbuf_get_bignum2(buf, &dsa_p)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_q)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_g)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_pub_key)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
goto out;
if (!DSA_set0_pqg(k->dsa, dsa_p, dsa_q, dsa_g)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_p = dsa_q = dsa_g = NULL; /* transferred */
if (!DSA_set0_key(k->dsa, dsa_pub_key, dsa_priv_key)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_pub_key = dsa_priv_key = NULL; /* transferred */
break;
case KEY_DSA_CERT:
- if ((dsa_priv_key = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, dsa_priv_key)) != 0)
+ (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0)
goto out;
if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
dsa_priv_key = NULL; /* transferred */
break;
# ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
goto out;
if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
r = SSH_ERR_EC_CURVE_MISMATCH;
goto out;
}
k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
- if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) {
+ if (k->ecdsa == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
- (r = sshbuf_get_bignum2(buf, exponent)))
+ (r = sshbuf_get_bignum2(buf, &exponent)))
goto out;
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
(r = sshkey_ec_validate_private(k->ecdsa)) != 0)
goto out;
break;
case KEY_ECDSA_CERT:
- if ((exponent = BN_new()) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, exponent)) != 0)
+ (r = sshbuf_get_bignum2(buf, &exponent)) != 0)
goto out;
if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
(r = sshkey_ec_validate_private(k->ecdsa)) != 0)
goto out;
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((rsa_n = BN_new()) == NULL ||
- (rsa_e = BN_new()) == NULL ||
- (rsa_d = BN_new()) == NULL ||
- (rsa_iqmp = BN_new()) == NULL ||
- (rsa_p = BN_new()) == NULL ||
- (rsa_q = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshbuf_get_bignum2(buf, rsa_n)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_e)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_d)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_p)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_q)) != 0)
+ if ((r = sshbuf_get_bignum2(buf, &rsa_n)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
goto out;
if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_n = rsa_e = rsa_d = NULL; /* transferred */
if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_p = rsa_q = NULL; /* transferred */
if ((r = check_rsa_length(k->rsa)) != 0)
goto out;
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
goto out;
break;
case KEY_RSA_CERT:
- if ((rsa_d = BN_new()) == NULL ||
- (rsa_iqmp = BN_new()) == NULL ||
- (rsa_p = BN_new()) == NULL ||
- (rsa_q = BN_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
if ((r = sshkey_froms(buf, &k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_d)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_iqmp)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_p)) != 0 ||
- (r = sshbuf_get_bignum2(buf, rsa_q)) != 0)
+ (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_iqmp)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_p)) != 0 ||
+ (r = sshbuf_get_bignum2(buf, &rsa_q)) != 0)
goto out;
if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_d = NULL; /* transferred */
if (!RSA_set0_factors(k->rsa, rsa_p, rsa_q)) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
rsa_p = rsa_q = NULL; /* transferred */
if ((r = check_rsa_length(k->rsa)) != 0)
goto out;
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
goto out;
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
goto out;
if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
k->ed25519_pk = ed25519_pk;
k->ed25519_sk = ed25519_sk;
ed25519_pk = ed25519_sk = NULL;
break;
case KEY_ED25519_CERT:
if ((r = sshkey_froms(buf, &k)) != 0 ||
(r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
goto out;
if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
k->ed25519_pk = ed25519_pk;
k->ed25519_sk = ed25519_sk;
ed25519_pk = ed25519_sk = NULL;
break;
#ifdef WITH_XMSS
case KEY_XMSS:
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
(r = sshkey_xmss_init(k, xmss_name)) != 0 ||
(r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
goto out;
if (pklen != sshkey_xmss_pklen(k) ||
sklen != sshkey_xmss_sklen(k)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
k->xmss_pk = xmss_pk;
k->xmss_sk = xmss_sk;
xmss_pk = xmss_sk = NULL;
/* optional internal state */
if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
goto out;
break;
case KEY_XMSS_CERT:
if ((r = sshkey_froms(buf, &k)) != 0 ||
(r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
(r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
goto out;
if (strcmp(xmss_name, k->xmss_name)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (pklen != sshkey_xmss_pklen(k) ||
sklen != sshkey_xmss_sklen(k)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
k->xmss_pk = xmss_pk;
k->xmss_sk = xmss_sk;
xmss_pk = xmss_sk = NULL;
/* optional internal state */
if ((r = sshkey_xmss_deserialize_state_opt(k, buf)) != 0)
goto out;
break;
#endif /* WITH_XMSS */
default:
r = SSH_ERR_KEY_TYPE_UNKNOWN;
goto out;
}
#ifdef WITH_OPENSSL
/* enable blinding */
switch (k->type) {
case KEY_RSA:
case KEY_RSA_CERT:
if (RSA_blinding_on(k->rsa, NULL) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
break;
}
#endif /* WITH_OPENSSL */
/* success */
r = 0;
if (kp != NULL) {
*kp = k;
k = NULL;
}
out:
free(tname);
free(curve);
#ifdef WITH_OPENSSL
BN_clear_free(exponent);
BN_clear_free(dsa_p);
BN_clear_free(dsa_q);
BN_clear_free(dsa_g);
BN_clear_free(dsa_pub_key);
BN_clear_free(dsa_priv_key);
BN_clear_free(rsa_n);
BN_clear_free(rsa_e);
BN_clear_free(rsa_d);
BN_clear_free(rsa_p);
BN_clear_free(rsa_q);
BN_clear_free(rsa_iqmp);
#endif /* WITH_OPENSSL */
sshkey_free(k);
freezero(ed25519_pk, pklen);
freezero(ed25519_sk, sklen);
free(xmss_name);
freezero(xmss_pk, pklen);
freezero(xmss_sk, sklen);
return r;
}
#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
int
sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
{
BN_CTX *bnctx;
EC_POINT *nq = NULL;
BIGNUM *order, *x, *y, *tmp;
int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
/*
* NB. This assumes OpenSSL has already verified that the public
* point lies on the curve. This is done by EC_POINT_oct2point()
* implicitly calling EC_POINT_is_on_curve(). If this code is ever
* reachable with public points not unmarshalled using
* EC_POINT_oct2point then the caller will need to explicitly check.
*/
if ((bnctx = BN_CTX_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
BN_CTX_start(bnctx);
/*
* We shouldn't ever hit this case because bignum_get_ecpoint()
* refuses to load GF2m points.
*/
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
NID_X9_62_prime_field)
goto out;
/* Q != infinity */
if (EC_POINT_is_at_infinity(group, public))
goto out;
if ((x = BN_CTX_get(bnctx)) == NULL ||
(y = BN_CTX_get(bnctx)) == NULL ||
(order = BN_CTX_get(bnctx)) == NULL ||
(tmp = BN_CTX_get(bnctx)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
EC_POINT_get_affine_coordinates_GFp(group, public,
x, y, bnctx) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
BN_num_bits(y) <= BN_num_bits(order) / 2)
goto out;
/* nQ == infinity (n == order of subgroup) */
if ((nq = EC_POINT_new(group)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (EC_POINT_is_at_infinity(group, nq) != 1)
goto out;
/* x < order - 1, y < order - 1 */
if (!BN_sub(tmp, order, BN_value_one())) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
goto out;
ret = 0;
out:
BN_CTX_free(bnctx);
EC_POINT_free(nq);
return ret;
}
int
sshkey_ec_validate_private(const EC_KEY *key)
{
BN_CTX *bnctx;
BIGNUM *order, *tmp;
int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
if ((bnctx = BN_CTX_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
BN_CTX_start(bnctx);
if ((order = BN_CTX_get(bnctx)) == NULL ||
(tmp = BN_CTX_get(bnctx)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* log2(private) > log2(order)/2 */
if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
BN_num_bits(order) / 2)
goto out;
/* private < order - 1 */
if (!BN_sub(tmp, order, BN_value_one())) {
ret = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
goto out;
ret = 0;
out:
BN_CTX_free(bnctx);
return ret;
}
void
sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
{
BIGNUM *x, *y;
BN_CTX *bnctx;
if (point == NULL) {
fputs("point=(NULL)\n", stderr);
return;
}
if ((bnctx = BN_CTX_new()) == NULL) {
fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
return;
}
BN_CTX_start(bnctx);
if ((x = BN_CTX_get(bnctx)) == NULL ||
(y = BN_CTX_get(bnctx)) == NULL) {
fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
return;
}
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
NID_X9_62_prime_field) {
fprintf(stderr, "%s: group is not a prime field\n", __func__);
return;
}
if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
bnctx) != 1) {
fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
__func__);
return;
}
fputs("x=", stderr);
BN_print_fp(stderr, x);
fputs("\ny=", stderr);
BN_print_fp(stderr, y);
fputs("\n", stderr);
BN_CTX_free(bnctx);
}
void
sshkey_dump_ec_key(const EC_KEY *key)
{
const BIGNUM *exponent;
sshkey_dump_ec_point(EC_KEY_get0_group(key),
EC_KEY_get0_public_key(key));
fputs("exponent=", stderr);
if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
fputs("(NULL)", stderr);
else
BN_print_fp(stderr, EC_KEY_get0_private_key(key));
fputs("\n", stderr);
}
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
static int
sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
const char *passphrase, const char *comment, const char *ciphername,
int rounds)
{
u_char *cp, *key = NULL, *pubkeyblob = NULL;
u_char salt[SALT_LEN];
char *b64 = NULL;
size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
u_int check;
int r = SSH_ERR_INTERNAL_ERROR;
struct sshcipher_ctx *ciphercontext = NULL;
const struct sshcipher *cipher;
const char *kdfname = KDFNAME;
struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
if (rounds <= 0)
rounds = DEFAULT_ROUNDS;
if (passphrase == NULL || !strlen(passphrase)) {
ciphername = "none";
kdfname = "none";
} else if (ciphername == NULL)
ciphername = DEFAULT_CIPHERNAME;
if ((cipher = cipher_by_name(ciphername)) == NULL) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((kdf = sshbuf_new()) == NULL ||
(encoded = sshbuf_new()) == NULL ||
(encrypted = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
blocksize = cipher_blocksize(cipher);
keylen = cipher_keylen(cipher);
ivlen = cipher_ivlen(cipher);
authlen = cipher_authlen(cipher);
if ((key = calloc(1, keylen + ivlen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (strcmp(kdfname, "bcrypt") == 0) {
arc4random_buf(salt, SALT_LEN);
if (bcrypt_pbkdf(passphrase, strlen(passphrase),
salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
(r = sshbuf_put_u32(kdf, rounds)) != 0)
goto out;
} else if (strcmp(kdfname, "none") != 0) {
/* Unsupported KDF type */
r = SSH_ERR_KEY_UNKNOWN_CIPHER;
goto out;
}
if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
key + keylen, ivlen, 1)) != 0)
goto out;
if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
(r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
(r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
(r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
(r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
(r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
(r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
goto out;
/* set up the buffer that will be encrypted */
/* Random check bytes */
check = arc4random();
if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
(r = sshbuf_put_u32(encrypted, check)) != 0)
goto out;
/* append private key and comment*/
if ((r = sshkey_private_serialize_opt(prv, encrypted,
SSHKEY_SERIALIZE_FULL)) != 0 ||
(r = sshbuf_put_cstring(encrypted, comment)) != 0)
goto out;
/* padding */
i = 0;
while (sshbuf_len(encrypted) % blocksize) {
if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
goto out;
}
/* length in destination buffer */
if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
goto out;
/* encrypt */
if ((r = sshbuf_reserve(encoded,
sshbuf_len(encrypted) + authlen, &cp)) != 0)
goto out;
if ((r = cipher_crypt(ciphercontext, 0, cp,
sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
goto out;
/* uuencode */
if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
sshbuf_reset(blob);
if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0)
goto out;
for (i = 0; i < strlen(b64); i++) {
if ((r = sshbuf_put_u8(blob, b64[i])) != 0)
goto out;
/* insert line breaks */
if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
goto out;
}
if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
goto out;
if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
goto out;
/* success */
r = 0;
out:
sshbuf_free(kdf);
sshbuf_free(encoded);
sshbuf_free(encrypted);
cipher_free(ciphercontext);
explicit_bzero(salt, sizeof(salt));
if (key != NULL) {
explicit_bzero(key, keylen + ivlen);
free(key);
}
if (pubkeyblob != NULL) {
explicit_bzero(pubkeyblob, pubkeylen);
free(pubkeyblob);
}
if (b64 != NULL) {
explicit_bzero(b64, strlen(b64));
free(b64);
}
return r;
}
static int
sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
struct sshkey **keyp, char **commentp)
{
char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
const struct sshcipher *cipher = NULL;
const u_char *cp;
int r = SSH_ERR_INTERNAL_ERROR;
size_t encoded_len;
size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
struct sshbuf *encoded = NULL, *decoded = NULL;
struct sshbuf *kdf = NULL, *decrypted = NULL;
struct sshcipher_ctx *ciphercontext = NULL;
struct sshkey *k = NULL;
u_char *key = NULL, *salt = NULL, *dp, pad, last;
u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
if ((encoded = sshbuf_new()) == NULL ||
(decoded = sshbuf_new()) == NULL ||
(decrypted = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* check preamble */
cp = sshbuf_ptr(blob);
encoded_len = sshbuf_len(blob);
if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
cp += MARK_BEGIN_LEN;
encoded_len -= MARK_BEGIN_LEN;
/* Look for end marker, removing whitespace as we go */
while (encoded_len > 0) {
if (*cp != '\n' && *cp != '\r') {
if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
goto out;
}
last = *cp;
encoded_len--;
cp++;
if (last == '\n') {
if (encoded_len >= MARK_END_LEN &&
memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
/* \0 terminate */
if ((r = sshbuf_put_u8(encoded, 0)) != 0)
goto out;
break;
}
}
}
if (encoded_len == 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* decode base64 */
if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0)
goto out;
/* check magic */
if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* parse public portion of key */
if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
(r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
(r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
(r = sshbuf_froms(decoded, &kdf)) != 0 ||
(r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
(r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
(r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
goto out;
if ((cipher = cipher_by_name(ciphername)) == NULL) {
r = SSH_ERR_KEY_UNKNOWN_CIPHER;
goto out;
}
if ((passphrase == NULL || strlen(passphrase) == 0) &&
strcmp(ciphername, "none") != 0) {
/* passphrase required */
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
r = SSH_ERR_KEY_UNKNOWN_CIPHER;
goto out;
}
if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (nkeys != 1) {
/* XXX only one key supported */
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* check size of encrypted key blob */
blocksize = cipher_blocksize(cipher);
if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* setup key */
keylen = cipher_keylen(cipher);
ivlen = cipher_ivlen(cipher);
authlen = cipher_authlen(cipher);
if ((key = calloc(1, keylen + ivlen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (strcmp(kdfname, "bcrypt") == 0) {
if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
(r = sshbuf_get_u32(kdf, &rounds)) != 0)
goto out;
if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
key, keylen + ivlen, rounds) < 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
}
/* check that an appropriate amount of auth data is present */
if (sshbuf_len(decoded) < encrypted_len + authlen) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* decrypt private portion of key */
if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
(r = cipher_init(&ciphercontext, cipher, key, keylen,
key + keylen, ivlen, 0)) != 0)
goto out;
if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded),
encrypted_len, 0, authlen)) != 0) {
/* an integrity error here indicates an incorrect passphrase */
if (r == SSH_ERR_MAC_INVALID)
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
goto out;
/* there should be no trailing data */
if (sshbuf_len(decoded) != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
/* check check bytes */
if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
(r = sshbuf_get_u32(decrypted, &check2)) != 0)
goto out;
if (check1 != check2) {
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
/* Load the private key and comment */
if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
(r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
goto out;
/* Check deterministic padding */
i = 0;
while (sshbuf_len(decrypted)) {
if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
goto out;
if (pad != (++i & 0xff)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
}
/* XXX decode pubkey and check against private */
/* success */
r = 0;
if (keyp != NULL) {
*keyp = k;
k = NULL;
}
if (commentp != NULL) {
*commentp = comment;
comment = NULL;
}
out:
pad = 0;
cipher_free(ciphercontext);
free(ciphername);
free(kdfname);
free(comment);
if (salt != NULL) {
explicit_bzero(salt, slen);
free(salt);
}
if (key != NULL) {
explicit_bzero(key, keylen + ivlen);
free(key);
}
sshbuf_free(encoded);
sshbuf_free(decoded);
sshbuf_free(kdf);
sshbuf_free(decrypted);
sshkey_free(k);
return r;
}
#ifdef WITH_OPENSSL
/* convert SSH v2 key in OpenSSL PEM format */
static int
sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
const char *_passphrase, const char *comment)
{
int success, r;
int blen, len = strlen(_passphrase);
u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
char *bptr;
BIO *bio = NULL;
if (len > 0 && len <= 4)
return SSH_ERR_PASSPHRASE_TOO_SHORT;
if ((bio = BIO_new(BIO_s_mem())) == NULL)
return SSH_ERR_ALLOC_FAIL;
switch (key->type) {
case KEY_DSA:
success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
cipher, passphrase, len, NULL, NULL);
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
cipher, passphrase, len, NULL, NULL);
break;
#endif
case KEY_RSA:
success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
cipher, passphrase, len, NULL, NULL);
break;
default:
success = 0;
break;
}
if (success == 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
}
if ((r = sshbuf_put(blob, bptr, blen)) != 0)
goto out;
r = 0;
out:
BIO_free(bio);
return r;
}
#endif /* WITH_OPENSSL */
/* Serialise "key" to buffer "blob" */
int
sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
int force_new_format, const char *new_format_cipher, int new_format_rounds)
{
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
if (force_new_format) {
return sshkey_private_to_blob2(key, blob, passphrase,
comment, new_format_cipher, new_format_rounds);
}
return sshkey_private_pem_to_blob(key, blob,
passphrase, comment);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
#ifdef WITH_XMSS
case KEY_XMSS:
#endif /* WITH_XMSS */
return sshkey_private_to_blob2(key, blob, passphrase,
comment, new_format_cipher, new_format_rounds);
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
}
#ifdef WITH_OPENSSL
static int
translate_libcrypto_error(unsigned long pem_err)
{
int pem_reason = ERR_GET_REASON(pem_err);
switch (ERR_GET_LIB(pem_err)) {
case ERR_LIB_PEM:
switch (pem_reason) {
case PEM_R_BAD_PASSWORD_READ:
case PEM_R_PROBLEMS_GETTING_PASSWORD:
case PEM_R_BAD_DECRYPT:
return SSH_ERR_KEY_WRONG_PASSPHRASE;
default:
return SSH_ERR_INVALID_FORMAT;
}
case ERR_LIB_EVP:
switch (pem_reason) {
case EVP_R_BAD_DECRYPT:
return SSH_ERR_KEY_WRONG_PASSPHRASE;
#ifdef EVP_R_BN_DECODE_ERROR
case EVP_R_BN_DECODE_ERROR:
#endif
case EVP_R_DECODE_ERROR:
#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
case EVP_R_PRIVATE_KEY_DECODE_ERROR:
#endif
return SSH_ERR_INVALID_FORMAT;
default:
return SSH_ERR_LIBCRYPTO_ERROR;
}
case ERR_LIB_ASN1:
return SSH_ERR_INVALID_FORMAT;
}
return SSH_ERR_LIBCRYPTO_ERROR;
}
static void
clear_libcrypto_errors(void)
{
while (ERR_get_error() != 0)
;
}
/*
* Translate OpenSSL error codes to determine whether
* passphrase is required/incorrect.
*/
static int
convert_libcrypto_error(void)
{
/*
* Some password errors are reported at the beginning
* of the error queue.
*/
if (translate_libcrypto_error(ERR_peek_error()) ==
SSH_ERR_KEY_WRONG_PASSPHRASE)
return SSH_ERR_KEY_WRONG_PASSPHRASE;
return translate_libcrypto_error(ERR_peek_last_error());
}
static int
pem_passphrase_cb(char *buf, int size, int rwflag, void *u)
{
char *p = (char *)u;
size_t len;
if (p == NULL || (len = strlen(p)) == 0)
return -1;
if (size < 0 || len > (size_t)size)
return -1;
memcpy(buf, p, len);
return (int)len;
}
static int
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp)
{
EVP_PKEY *pk = NULL;
struct sshkey *prv = NULL;
BIO *bio = NULL;
int r;
if (keyp != NULL)
*keyp = NULL;
if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
return SSH_ERR_ALLOC_FAIL;
if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
(int)sshbuf_len(blob)) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
clear_libcrypto_errors();
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb,
(char *)passphrase)) == NULL) {
/*
* libcrypto may return various ASN.1 errors when attempting
* to parse a key with an incorrect passphrase.
* Treat all format errors as "incorrect passphrase" if a
* passphrase was supplied.
*/
if (passphrase != NULL && *passphrase != '\0')
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
else
r = convert_libcrypto_error();
goto out;
}
if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
(type == KEY_UNSPEC || type == KEY_RSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
prv->rsa = EVP_PKEY_get1_RSA(pk);
prv->type = KEY_RSA;
#ifdef DEBUG_PK
RSA_print_fp(stderr, prv->rsa, 8);
#endif
if (RSA_blinding_on(prv->rsa, NULL) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
if ((r = check_rsa_length(prv->rsa)) != 0)
goto out;
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
prv->dsa = EVP_PKEY_get1_DSA(pk);
prv->type = KEY_DSA;
#ifdef DEBUG_PK
DSA_print_fp(stderr, prv->dsa, 8);
#endif
#ifdef OPENSSL_HAS_ECC
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
(type == KEY_UNSPEC || type == KEY_ECDSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
prv->type = KEY_ECDSA;
prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
if (prv->ecdsa_nid == -1 ||
sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
sshkey_ec_validate_private(prv->ecdsa) != 0) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
# ifdef DEBUG_PK
if (prv != NULL && prv->ecdsa != NULL)
sshkey_dump_ec_key(prv->ecdsa);
# endif
#endif /* OPENSSL_HAS_ECC */
} else {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
r = 0;
if (keyp != NULL) {
*keyp = prv;
prv = NULL;
}
out:
BIO_free(bio);
EVP_PKEY_free(pk);
sshkey_free(prv);
return r;
}
#endif /* WITH_OPENSSL */
int
sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp, char **commentp)
{
int r = SSH_ERR_INTERNAL_ERROR;
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
switch (type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
return sshkey_parse_private_pem_fileblob(blob, type,
passphrase, keyp);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
#ifdef WITH_XMSS
case KEY_XMSS:
#endif /* WITH_XMSS */
return sshkey_parse_private2(blob, type, passphrase,
keyp, commentp);
case KEY_UNSPEC:
r = sshkey_parse_private2(blob, type, passphrase, keyp,
commentp);
/* Do not fallback to PEM parser if only passphrase is wrong. */
if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE)
return r;
#ifdef WITH_OPENSSL
return sshkey_parse_private_pem_fileblob(blob, type,
passphrase, keyp);
#else
return SSH_ERR_INVALID_FORMAT;
#endif /* WITH_OPENSSL */
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
}
int
sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
struct sshkey **keyp, char **commentp)
{
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
passphrase, keyp, commentp);
}
#ifdef WITH_XMSS
/*
* serialize the key with the current state and forward the state
* maxsign times.
*/
int
sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
u_int32_t maxsign, sshkey_printfn *pr)
{
int r, rupdate;
if (maxsign == 0 ||
sshkey_type_plain(k->type) != KEY_XMSS)
return sshkey_private_serialize_opt(k, b,
SSHKEY_SERIALIZE_DEFAULT);
if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
(r = sshkey_private_serialize_opt(k, b,
SSHKEY_SERIALIZE_STATE)) != 0 ||
(r = sshkey_xmss_forward_state(k, maxsign)) != 0)
goto out;
r = 0;
out:
if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
if (r == 0)
r = rupdate;
}
return r;
}
u_int32_t
sshkey_signatures_left(const struct sshkey *k)
{
if (sshkey_type_plain(k->type) == KEY_XMSS)
return sshkey_xmss_signatures_left(k);
return 0;
}
int
sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
{
if (sshkey_type_plain(k->type) != KEY_XMSS)
return SSH_ERR_INVALID_ARGUMENT;
return sshkey_xmss_enable_maxsign(k, maxsign);
}
int
sshkey_set_filename(struct sshkey *k, const char *filename)
{
if (k == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if (sshkey_type_plain(k->type) != KEY_XMSS)
return 0;
if (filename == NULL)
return SSH_ERR_INVALID_ARGUMENT;
if ((k->xmss_filename = strdup(filename)) == NULL)
return SSH_ERR_ALLOC_FAIL;
return 0;
}
#else
int
sshkey_private_serialize_maxsign(const struct sshkey *k, struct sshbuf *b,
u_int32_t maxsign, sshkey_printfn *pr)
{
return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
}
u_int32_t
sshkey_signatures_left(const struct sshkey *k)
{
return 0;
}
int
sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign)
{
return SSH_ERR_INVALID_ARGUMENT;
}
int
sshkey_set_filename(struct sshkey *k, const char *filename)
{
if (k == NULL)
return SSH_ERR_INVALID_ARGUMENT;
return 0;
}
#endif /* WITH_XMSS */
diff --git a/sshkey.h b/sshkey.h
index f6a007fdff35..a91e60436358 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,277 +1,278 @@
-/* $OpenBSD: sshkey.h,v 1.30 2018/09/14 04:17:44 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.31 2019/01/20 22:51:37 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SSHKEY_H
#define SSHKEY_H
#include <sys/types.h>
#ifdef WITH_OPENSSL
#include <openssl/rsa.h>
#include <openssl/dsa.h>
# ifdef OPENSSL_HAS_ECC
# include <openssl/ec.h>
+# include <openssl/ecdsa.h>
# else /* OPENSSL_HAS_ECC */
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
#else /* WITH_OPENSSL */
# define BIGNUM void
# define RSA void
# define DSA void
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
#endif /* WITH_OPENSSL */
#define SSH_RSA_MINIMUM_MODULUS_SIZE 1024
#define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20)
struct sshbuf;
/* Key types */
enum sshkey_types {
KEY_RSA,
KEY_DSA,
KEY_ECDSA,
KEY_ED25519,
KEY_RSA_CERT,
KEY_DSA_CERT,
KEY_ECDSA_CERT,
KEY_ED25519_CERT,
KEY_XMSS,
KEY_XMSS_CERT,
KEY_UNSPEC
};
/* Default fingerprint hash */
#define SSH_FP_HASH_DEFAULT SSH_DIGEST_SHA256
/* Fingerprint representation formats */
enum sshkey_fp_rep {
SSH_FP_DEFAULT = 0,
SSH_FP_HEX,
SSH_FP_BASE64,
SSH_FP_BUBBLEBABBLE,
SSH_FP_RANDOMART
};
/* Private key serialisation formats, used on the wire */
enum sshkey_serialize_rep {
SSHKEY_SERIALIZE_DEFAULT = 0,
SSHKEY_SERIALIZE_STATE = 1,
SSHKEY_SERIALIZE_FULL = 2,
SSHKEY_SERIALIZE_INFO = 254,
};
/* key is stored in external hardware */
#define SSHKEY_FLAG_EXT 0x0001
#define SSHKEY_CERT_MAX_PRINCIPALS 256
/* XXX opaquify? */
struct sshkey_cert {
struct sshbuf *certblob; /* Kept around for use on wire */
u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
u_int64_t serial;
char *key_id;
u_int nprincipals;
char **principals;
u_int64_t valid_after, valid_before;
struct sshbuf *critical;
struct sshbuf *extensions;
struct sshkey *signature_key;
char *signature_type;
};
/* XXX opaquify? */
struct sshkey {
int type;
int flags;
RSA *rsa;
DSA *dsa;
int ecdsa_nid; /* NID of curve */
EC_KEY *ecdsa;
u_char *ed25519_sk;
u_char *ed25519_pk;
char *xmss_name;
char *xmss_filename; /* for state file updates */
void *xmss_state; /* depends on xmss_name, opaque */
u_char *xmss_sk;
u_char *xmss_pk;
struct sshkey_cert *cert;
};
#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES
struct sshkey *sshkey_new(int);
void sshkey_free(struct sshkey *);
int sshkey_equal_public(const struct sshkey *,
const struct sshkey *);
int sshkey_equal(const struct sshkey *, const struct sshkey *);
char *sshkey_fingerprint(const struct sshkey *,
int, enum sshkey_fp_rep);
int sshkey_fingerprint_raw(const struct sshkey *k,
int, u_char **retp, size_t *lenp);
const char *sshkey_type(const struct sshkey *);
const char *sshkey_cert_type(const struct sshkey *);
int sshkey_format_text(const struct sshkey *, struct sshbuf *);
int sshkey_write(const struct sshkey *, FILE *);
int sshkey_read(struct sshkey *, char **);
u_int sshkey_size(const struct sshkey *);
int sshkey_generate(int type, u_int bits, struct sshkey **keyp);
int sshkey_from_private(const struct sshkey *, struct sshkey **);
int sshkey_type_from_name(const char *);
int sshkey_is_cert(const struct sshkey *);
int sshkey_type_is_cert(int);
int sshkey_type_plain(int);
int sshkey_to_certified(struct sshkey *);
int sshkey_drop_cert(struct sshkey *);
int sshkey_cert_copy(const struct sshkey *, struct sshkey *);
int sshkey_cert_check_authority(const struct sshkey *, int, int,
const char *, const char **);
size_t sshkey_format_cert_validity(const struct sshkey_cert *,
char *, size_t) __attribute__((__bounded__(__string__, 2, 3)));
int sshkey_check_cert_sigtype(const struct sshkey *, const char *);
int sshkey_certify(struct sshkey *, struct sshkey *, const char *);
/* Variant allowing use of a custom signature function (e.g. for ssh-agent) */
typedef int sshkey_certify_signer(const struct sshkey *, u_char **, size_t *,
const u_char *, size_t, const char *, u_int, void *);
int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *,
sshkey_certify_signer *, void *);
int sshkey_ecdsa_nid_from_name(const char *);
int sshkey_curve_name_to_nid(const char *);
const char * sshkey_curve_nid_to_name(int);
u_int sshkey_curve_nid_to_bits(int);
int sshkey_ecdsa_bits_to_nid(int);
int sshkey_ecdsa_key_to_nid(EC_KEY *);
int sshkey_ec_nid_to_hash_alg(int nid);
int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *);
int sshkey_ec_validate_private(const EC_KEY *);
const char *sshkey_ssh_name(const struct sshkey *);
const char *sshkey_ssh_name_plain(const struct sshkey *);
int sshkey_names_valid2(const char *, int);
char *sshkey_alg_list(int, int, int, char);
int sshkey_from_blob(const u_char *, size_t, struct sshkey **);
int sshkey_fromb(struct sshbuf *, struct sshkey **);
int sshkey_froms(struct sshbuf *, struct sshkey **);
int sshkey_to_blob(const struct sshkey *, u_char **, size_t *);
int sshkey_to_base64(const struct sshkey *, char **);
int sshkey_putb(const struct sshkey *, struct sshbuf *);
int sshkey_puts(const struct sshkey *, struct sshbuf *);
int sshkey_puts_opts(const struct sshkey *, struct sshbuf *,
enum sshkey_serialize_rep);
int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
int sshkey_sign(const struct sshkey *, u_char **, size_t *,
const u_char *, size_t, const char *, u_int);
int sshkey_verify(const struct sshkey *, const u_char *, size_t,
const u_char *, size_t, const char *, u_int);
int sshkey_check_sigtype(const u_char *, size_t, const char *);
const char *sshkey_sigalg_by_name(const char *);
/* for debug */
void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
void sshkey_dump_ec_key(const EC_KEY *);
/* private key parsing and serialisation */
int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf);
int sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *buf,
enum sshkey_serialize_rep);
int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
/* private key file format parsing and serialisation */
int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
int force_new_format, const char *new_format_cipher, int new_format_rounds);
int sshkey_parse_private_fileblob(struct sshbuf *buffer,
const char *passphrase, struct sshkey **keyp, char **commentp);
int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp, char **commentp);
/* XXX should be internal, but used by ssh-keygen */
int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
/* stateful keys (e.g. XMSS) */
#ifdef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS
typedef void sshkey_printfn(const char *, ...);
#else
typedef void sshkey_printfn(const char *, ...) __attribute__((format(printf, 1, 2)));
#endif
int sshkey_set_filename(struct sshkey *, const char *);
int sshkey_enable_maxsign(struct sshkey *, u_int32_t);
u_int32_t sshkey_signatures_left(const struct sshkey *);
int sshkey_forward_state(const struct sshkey *, u_int32_t, sshkey_printfn *);
int sshkey_private_serialize_maxsign(const struct sshkey *key, struct sshbuf *buf,
u_int32_t maxsign, sshkey_printfn *pr);
#ifdef SSHKEY_INTERNAL
int ssh_rsa_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
const char *ident);
int ssh_rsa_verify(const struct sshkey *key,
const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
const char *alg);
int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
int ssh_dss_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat);
int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
int ssh_ecdsa_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat);
int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
int ssh_ed25519_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat);
int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat);
int ssh_xmss_verify(const struct sshkey *key,
const u_char *signature, size_t signaturelen,
const u_char *data, size_t datalen, u_int compat);
#endif
#if !defined(WITH_OPENSSL)
# undef RSA
# undef DSA
# undef EC_KEY
# undef EC_GROUP
# undef EC_POINT
#elif !defined(OPENSSL_HAS_ECC)
# undef EC_KEY
# undef EC_GROUP
# undef EC_POINT
#endif
#endif /* SSHKEY_H */
diff --git a/version.h b/version.h
index 422dfbc3a225..806ead9a6cef 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
-/* $OpenBSD: version.h,v 1.83 2018/10/10 16:43:49 deraadt Exp $ */
+/* $OpenBSD: version.h,v 1.84 2019/04/03 15:48:45 djm Exp $ */
-#define SSH_VERSION "OpenSSH_7.9"
+#define SSH_VERSION "OpenSSH_8.0"
#define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE

File Metadata

Mime Type
application/octet-stream
Expires
Fri, May 24, 1:40 PM (2 d)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
IZ_WMuT2JQgL
Default Alt Text
(5 MB)

Event Timeline